[SOLVED] SET /a -- Random Number?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
g2geo94
Posts: 3
Joined: 16 May 2011 08:05

[SOLVED] SET /a -- Random Number?

#1 Post by g2geo94 » 16 May 2011 08:14

I really hope that this doesn't already exist and that I don't just suck at searching....

Anyways, I'm writing a small quiz game in Batch, and am wondering how to create and limit a random number generator. I have reason to believe this is possible using "set /a," however I am not positive on this, nor how to make it work.

What I want:
A Random Number Generator, limited to numbers in between 'x' and 'y', where 'x' and 'y' are defined before hand, and the ability of the batch file to then direct to a different section of the file, by section title of the number defined.
Something like:
RAND#= Z
GOTO Z
:T
Stuff relating to T
:Z
Stuff relating to Z

Thanks ahead of time,
Geoffrey
Last edited by g2geo94 on 16 May 2011 09:38, edited 1 time in total.

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: SET /a -- Random Number?

#2 Post by Ed Dyreen » 16 May 2011 08:25

'
[edit] probably too difficult, see dbenhams post below please !

Code: Select all

::for /f "usebackq tokens=1-3 delims=¦" %%b in ( '"MinimumSTR"¦"MaximumSTR"¦"StoreVAR"' ) do %Get.RandomNumber.TokenSTR% %()%
::
for %%? in ( Get.RandomNumber.TokenSTR ) do set "%%~?=set /a Minimum = %%~b ^&set /a Maximum = %%~c ^&set /a interval = ^^^!Maximum^^^! - ^^^!Minimum^^^! ^&call set /a %%~d = %%Random%% ^&set /a %%~d = ^^^!%%~d^^^! * ^^^!interval^^^! / 32767 + ^^^!Minimum^^^! ^&( echo. ^&echo. ^&set /p "?= %%~d : '^^^!%%~d^^^!' [OK]" ^<nul ) "

g2geo94
Posts: 3
Joined: 16 May 2011 08:05

Re: SET /a -- Random Number?

#3 Post by g2geo94 » 16 May 2011 08:33

This is going to more than likely seem very noobish, but could you break that down a bit?

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: SET /a -- Random Number?

#4 Post by Ed Dyreen » 16 May 2011 08:55

'
I am not good in english, what u mean by 'seem very noobish' ? sorry.

Code: Select all


@echo off &SetLocal EnableExtensions EnableDelayedExpansion

::I want a randomnumber, & i want to jump based on this number right ?

::create executable variable @Get.RandomNumber.TokenSTR
for %%? in ( Get.RandomNumber.TokenSTR ) do set "%%~?=set /a Minimum = %%~b ^&set /a Maximum = %%~c ^&set /a interval = ^^^!Maximum^^^! - ^^^!Minimum^^^! ^&call set /a %%~d = %%Random%% ^&set /a %%~d = ^^^!%%~d^^^! * ^^^!interval^^^! / 32767 + ^^^!Minimum^^^! ^&( echo. ^&echo. ^&set /p "?= %%~d : '^^^!%%~d^^^!' [OK]" ^<nul ) "


::This is how you use it
::for /f "usebackq tokens=1-3 delims=¦" %%b in ( '"MinimumSTR"¦"MaximumSTR"¦"StoreVAR"' ) do %Get.RandomNumber.TokenSTR% %()%

::Lets use it...

echo.
echo.
for /f "usebackq tokens=1-3 delims=¦" %%b in ( '"1"¦"4"¦"RandomNumber"' ) do %Get.RandomNumber.TokenSTR% %()% >nul
call :LABEL%RandomNumber%

for /f "usebackq tokens=1-3 delims=¦" %%b in ( '"1"¦"4"¦"RandomNumber"' ) do %Get.RandomNumber.TokenSTR% %()% >nul
call :LABEL%RandomNumber%

for /f "usebackq tokens=1-3 delims=¦" %%b in ( '"1"¦"4"¦"RandomNumber"' ) do %Get.RandomNumber.TokenSTR% %()% >nul
call :LABEL%RandomNumber%

goto :Exit ()

:LABEL1
echo.LABEL1
goto :EOF ()
:LABEL2
echo.LABEL2
goto :EOF ()
:LABEL3
echo.LABEL3
goto :EOF ()
:LABEL4
echo.LABEL4
goto :EOF ()


:Exit
pause
exit 0


dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: SET /a -- Random Number?

#5 Post by dbenham » 16 May 2011 09:10

Random numbers are actually very easy with batch. %RANDOM% is a dynamic pseudo variable that returns a pseudo random number between 0 and 32767. The only thing remaining is to use the modulo operator (%, or %% in a batch file) to limit the values between 0 and Count, and add the minimum required value to set the range.

See if this can get you started:

Code: Select all

@echo off
echo:
echo Testing :random without RtnVar
echo:
for /l %%n in (1,1,10) do call :random 1 10
echo:
echo:-------------------------
echo:
echo Testing :random with RtnVar in order to implement random GOTO
echo:
call :random 1, 5 label
goto :%label%

:1
echo option :1
exit /b

:2
echo option :2
exit /b

:3
echo option :3
exit /b

:4
echo option :4
exit /b

:5
echo option :5
exit /b


:random Min Max [RtnVar]
::
:: Compute a pseudo random integral value between numeric values Min and Max
::
:: Return the value in variable RtnVar
:: or display the value if RtnVar not specified
::
:: Min and Max may be specified using any expression supported
:: by SET /A
::
  setlocal
  set /a rtn=%random% %% ((%~2)-(%~1)+1) + (%~1)
  (endlocal
    if "%~3" neq "" (set %~3=%rtn%) else echo:%rtn%
  )
exit /b

g2geo94
Posts: 3
Joined: 16 May 2011 08:05

Re: SET /a -- Random Number?

#6 Post by g2geo94 » 16 May 2011 09:36

Thank you, dbenham. This should work perfectly.
@Ed, "sound very noobish" is basically saying "I'm gonna sound very stupid and naive in this subject of matter"

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: [SOLVED] SET /a -- Random Number?

#7 Post by Ed Dyreen » 16 May 2011 10:53

I did not know about the modulo which is quite handy,

Thank U dbenham

Code: Select all

::for /f "usebackq tokens=1-3 delims=¦" %%b in ( '"MinimumSTR"¦"MaximumSTR"¦"StoreVAR"' ) do %Get.RandomNumber.TokenSTR% %()%
::
for %%? in ( Get.RandomNumber.TokenSTR ) do set "%%~?=set /a Minimum = %%~b &set /a Maximum = %%~c &call set /a %%~d = %%Random%% %%%% ^( %%Maximum%% - %%Minimum%% + 1 ^) + %%Minimum%% &( echo. &echo. &call set /p "?= %%~d : %%%%~d%% [OK]" <nul ) "


One last thing;

using call in combination with goto gives u:
-nice looking code
-easy to debug
-slow execution times, good for small (100kb)-- scripts

avoiding call in combination with goto gives u:
-bad looking code
-hard to debug
-fast executing time, good for large (100kb)++ scripts

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: [SOLVED] SET /a -- Random Number?

#8 Post by dbenham » 17 May 2011 22:56

Hi Ed Dyreen

It took me a while to parse your code, but I finally figured out what was going on. You are basically creating and calling a "macro" that takes three arguments. I hadn't seen that batch technique before. (It's a shame DOSKEY macros can't be used in batch!)

It's kind of cool, but it seems like your code is much more complicated than it needs to be.

I came up with the following which I think is simpler to code and easier to follow:

Code: Select all

echo off
SetLocal

::create "macro" that takes three arguments
set "macroRandom=call set /a %%~c= %%Random%% %%%% ((%%~b)-(%%~a)+1) + (%%~a)"

::a few equivalent examples of calling the "macro"
for /f "tokens=1-3"                   %%a in ("10 20 result1")      do %macroRandom%
for /f "tokens=1-3 delims=,"          %%a in ("10,20,result2")      do %macroRandom%
for /f "tokens=1-3 delims=,"          %%a in ("5 + 5,20,result3")   do %macroRandom%
for /f "usebackq tokens=1-3 delims=:" %%a in ('5 + 5:20:result4')   do %macroRandom%
for /f "usebackq tokens=1-3 delims=," %%a in ('5 + 5^,20^,result5') do %macroRandom%
set /a min=10, max=20
for /f "tokens=1-3"                   %%a in ("min max result6")    do %macroRandom%

::hide more of the details in a two part macro
set "randomPart1=for /f "tokens=1-3" %%a in"
set "randomPart2=do call set /a %%~c= %%Random%% %%%% ((%%~b)-(%%~a)+1) + (%%~a)"

::call the two part macro
%randomPart1% ("10 20 result7") %randomPart2%

::display results of "calls"
set result


Dave Benham

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: [SOLVED] SET /a -- Random Number?

#9 Post by Ed Dyreen » 18 May 2011 07:42

'
It pleases me that someone I look up to likes my macro technique :D

I have never seen it before either &I wonder if I am the only that used it until now. Probably not :lol:

The reason for this technique is frustration. Frustration because my script is build upon sort of a sjablon consisting of several files that are used like we use #include in a high level language.

Frustrated with the time consuming calls &goto commands I discovered/devellopped a much faster 'macro' technique.
The difference between this macro and a function is that a function would have to be called EVERY time it is used.
A variable/macro gets loaded into memory only once &doesn't need anything to be jumped to or read from to be used.
That's why it is about a factor 1000 faster than any similar function.

You are doing basically the same thing as I &yes my macro is more complicated than needs to be. But really at those speeds the delay is hardly measurable. The reason it is more complicated is because I have more than one macro to load &am always looking for standardization (similar function should look alike if possible).

The thing you have left out at the end ( echo hello world ) is actually quite handy, it displays the results which can be easily suppressed if you send the output to nul.

Code: Select all

%Exec.MACRO% >nul
But hey, every person has his own programming style &that in fact is a good thing!

For the moment I am converting many simple functions to macros since it is only for about a month I use this technique &there is a lot that still needs to be done.

In the end (whenever that is) my sjablon consists of only one function that uses a loop

set "@MACRO=set "RULE=while this is true" &call :LoopUntil"

for something in ( something ) do @MACRO

end of program

::Functions >>
:LoopUntil ( /rule: "ByVAR" )

%eval% (
::true loop
goto :LOOPUntil "()"
)
:: false
goto :eof

::Functions<<

:EOF ()

In the past I was worried about readability, in the present speed has become my biggest enemy.
These days every second counts; a faster batch gives a more professional look &users would not understand when simple things take time.

nitt
Posts: 218
Joined: 22 Apr 2011 02:43

Re: SET /a -- Random Number?

#10 Post by nitt » 23 May 2011 16:05

Ed Dyreen wrote:

Code: Select all

::for /f "usebackq tokens=1-3 delims=¦" %%b in ( '"MinimumSTR"¦"MaximumSTR"¦"StoreVAR"' ) do %Get.RandomNumber.TokenSTR% %()%
::
for %%? in ( Get.RandomNumber.TokenSTR ) do set "%%~?=set /a Minimum = %%~b ^&set /a Maximum = %%~c ^&set /a interval = ^^^!Maximum^^^! - ^^^!Minimum^^^! ^&call set /a %%~d = %%Random%% ^&set /a %%~d = ^^^!%%~d^^^! * ^^^!interval^^^! / 32767 + ^^^!Minimum^^^! ^&( echo. ^&echo. ^&set /p "?= %%~d : '^^^!%%~d^^^!' [OK]" ^<nul ) "


...You are trying to make yourself look smart but that's actually crap.

Code: Select all

@echo off
:check
set rnd=%random%
if %rnd% GTR 100 goto check
if %rnd% LSS 0 goto check

echo %rnd%
pause


That's it! That's all you freaking have to do! 100 is the max, 0 is the min. Just change those.

I know this is an old thread, but I hate how people try to insult new programmers in this way. It's a jerk move.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: [SOLVED] SET /a -- Random Number?

#11 Post by dbenham » 23 May 2011 17:18

Not cool Nit - I seem to recall an expression - "The pot is calling the kettle black".

I discourage anyone from using Nitt's naive solution, unless you want your computer executing perhaps thousands of unnecessary loops. Each pass has only a 0.3% chance of getting a number between 0 and 100. On average it takes 365 checks to achieve a number less than 100 (based on a 100 call sample). In one case a single call required 1872 checks. Of course the situation is even worse if your max is less than 100.

The modulo solution in my 1st post on this thread is simple and fast.

Dave Benham

nitt
Posts: 218
Joined: 22 Apr 2011 02:43

Re: [SOLVED] SET /a -- Random Number?

#12 Post by nitt » 24 May 2011 15:53

dbenham wrote:Not cool Nit - I seem to recall an expression - "The pot is calling the kettle black".

I discourage anyone from using Nitt's naive solution, unless you want your computer executing perhaps thousands of unnecessary loops. Each pass has only a 0.3% chance of getting a number between 0 and 100. On average it takes 365 checks to achieve a number less than 100 (based on a 100 call sample). In one case a single call required 1872 checks. Of course the situation is even worse if your max is less than 100.

The modulo solution in my 1st post on this thread is simple and fast.

Dave Benham


Modulo is not truly random. And thanks for insulting me when you really don't know what you're even getting at.

My point was that you people are trolling when you post codes like the one I quoted. I know modulo, but Batch has an easier way around it.

And how is < 0.1 seconds a long time to wait? Saying the code is bad because it is slow is naive. This is Batch, we aren't working with large projects in C++ or anything.

You know he wouldn't understand your code, either. That's trolling. When people are new, you work at their level. You people are such jerks.

paultomasi
Posts: 25
Joined: 24 Feb 2009 14:52
Location: UK
Contact:

Re: [SOLVED] SET /a -- Random Number?

#13 Post by paultomasi » 26 Nov 2011 16:02

Well said nitt however, let's look at the proper way to generate random numbers between (and including) 'min' and 'max'.

The following code will generate a random number between 5..10 inclusively:

Code: Select all

set min=5
set max=10
set /a range=max-min +1

set /a rnd=%random% %%%range% +%min%
echo %rnd%

taripo
Posts: 227
Joined: 01 Aug 2011 13:48

Re: SET /a -- Random Number?

#14 Post by taripo » 27 Nov 2011 15:42

trying to find a delete option.. i've put this post elsewhere. and copied replies to it too elsewhere, to clean up this thread since it contains Ed's valuable discovery of macros!
i'd like to delete this post of mine and those other posts of mine in this thread which just contain the words del.
Last edited by taripo on 13 Dec 2011 15:44, edited 4 times in total.

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: SET /a -- Random Number?

#15 Post by Ed Dyreen » 27 Nov 2011 16:10

'
taripo wrote:If I put that in a batch file, and TYPE blah.bat it shows ª
I have no clue, I don't have that problem :(

Code: Select all

C:\PROFSYS\ADMIN>prompt $

@echo off
for /f "tokens=1-26 delims=¦" %a in ( "this¦works" ) do echo.a=%~a_ &echo.b=%~b_

a=this_
b=works_
You can use whatever delimiter you like though...

Post Reply