125

How to use random in BATCH script?

IAdapter
  • 62,595
  • 73
  • 179
  • 242
  • 1
    why do you want to do this specifically in batch? – Mat Apr 25 '11 at 10:21
  • There is a very interesting [post on SuperUser](http://superuser.com/a/588473) related to random numbers in batch scripts worth being referenced here... – aschipfl Aug 27 '15 at 23:47

14 Answers14

148

%RANDOM% gives you a random number between 0 and 32767.

Using an expression like SET /A test=%RANDOM% * 100 / 32768 + 1, you can change the range to anything you like (here the range is [1…100] instead of [0…32767]).

mousio
  • 10,079
  • 4
  • 34
  • 43
  • 9
    Given the specific problem, you will very likely be using some kind of loop? Then you should indeed be using delayed expansion e.g. via `SETLOCAL ENABLEDELAYEDEXPANSION` and using `!RANDOM!` instead of `%RANDOM%`, like Eugene posted. – mousio Apr 25 '11 at 10:49
  • 21
    A more general expression would be `%RANDOM% * (%maxval% - %minval% + 1) / 32768 + %minval%`; just set `minval` and `maxval` to the appropriate values first. – mousio Apr 29 '11 at 07:44
  • 1
    See also [indiv's answer](http://stackoverflow.com/questions/5777400/how-to-use-random-in-batch-script/5823530#5823530) – mousio May 09 '11 at 08:06
  • why does `echo random = %random%` always give me a number in the 4000 range? (It seems to be slowly increasing) – john k Feb 27 '22 at 16:06
63

%RANDOM% gives you a random number between 0 and 32767.

You can control the number's range with:

set /a num=%random% %%100

- will produce number between 0~99.

This one:

set /a num=%random% %%100 +1

- will produce number between 1~100.

GaryNg
  • 1,103
  • 9
  • 16
  • 15
    Note that this will not be uniformly distributed! Taking the 0~99 example, the numbers 0~67 will occur slightly more often than the numbers 68~99 because 32767 modulo 100 is 67 and not 0 as it would have to be for a uniform distribution. (This `%random% %%100` is no magic syntax but actually `%random % %% 100` with one less space, where the `%%` is just an escaped `%` which stands for modulo.) – CherryDT Apr 27 '16 at 08:56
  • 2
    I'm getting "Missing operand" error when trying this on Windows 10. Looks like you need just a singe % for modulo. – Calmarius Nov 25 '19 at 10:14
  • 3
    @Calmarius If you use this on the command line then you need 1 %. In a .BAT file you need 2. That's because in a .BAT file, %100 has special meaning, which is the 100th argument to the .bat file when executed with arguments. – Ike Starnes Feb 12 '21 at 21:57
  • @IkeStarnes Actually Batch can only access arguments up to `%9`; `%100` means `%1` with two zeros suffixed. – Neil Nov 16 '21 at 10:27
22

You'll probably want to get several random numbers, and may want to be able to specify a different range for each one, so you should define a function. In my example, I generate numbers from 25 through 30 with call:rand 25 30. And the result is in RAND_NUM after that function exits.

@echo off & setlocal EnableDelayedExpansion

for /L %%a in (1 1 10) do (
        call:rand 25 30
        echo !RAND_NUM!
)

goto:EOF

REM The script ends at the above goto:EOF.  The following are functions.

REM rand()
REM Input: %1 is min, %2 is max.
REM Output: RAND_NUM is set to a random number from min through max.
:rand
SET /A RAND_NUM=%RANDOM% * (%2 - %1 + 1) / 32768 + %1
goto:EOF
indiv
  • 17,306
  • 6
  • 61
  • 82
6
set /a number=%random% %% [maximum]-[minimum]

example "

set /a number=%random% %% 100-50

will give a random number between 100 and 50. Be sure to only use one percentage sign as the operand if you are not using the line in a batch script!

Jacob
  • 77
  • 1
  • 1
6
@echo off & setLocal EnableDelayedExpansion

for /L %%a in (1 1 100) do (
echo !random!
)
Evgeny Gavrin
  • 7,627
  • 1
  • 22
  • 27
5

You could do it this way, which does not require EnableDelayedExpansion

:choosenamea
cls
set /a choosemname=%random%

if %choosemname% GTR %max% goto choosenameb
if %choosemname% LSS %min% goto choosenameb
goto gotnamenow

where max is your max and min is your minimum. This is not very efficient since might take a lot of rounds if your range is too small. Also, this will not work for numbers larger than 32767.

calebhk98
  • 157
  • 1
  • 4
  • 15
4

Let's say you want a number 1-5; you could use the following:

    :LOOP
    set NUM=%random:~-1,1%
    if %NUM% GTR 5 (
    goto LOOP )
    goto NEXT

Or you could use :~1,1 in place of :~-1,1. The :~-1,1 is not needed, but it greatly reduces the amount of time it takes to hit the right range. Let's say you want a number 1-50, we need to decide between 2 digits and 1 digit. Use:

    :LOOP
    set RAN1=%random:~-1,1%
    if %RAN1% GTR 5 (
    goto 1 )
    if %RAN1%==5 (
    goto LOOP )
    goto 2

    :1
    set NUM=%random:~-1,1%
    goto NEXT

    :2
    set NUM=%random:~-1,2%
    goto NEXT

You can add more to this algorithm to decide between large ranges, such as 1-1000.

  • 3
    Why would you use `goto` when you can have one liners like above? Other solutions let you explicitly specify the range. What is the advantage of your code? – Max Leske Apr 16 '14 at 20:46
3
@echo off
title Professional Hacker
color 02
:matrix
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%% 
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%% 
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%% 
goto matrix
Community
  • 1
  • 1
Sinji58
  • 47
  • 1
3

If you will divide by some large value you will get a huge amount of duplicates one after other. What you need to do is to take modulo of the %RANDOM% value:

@echo off
REM 
SET maxvalue=10
SET minvalue=1

SETLOCAL 
SET /A tmpRandom=((%RANDOM%)%%(%maxvalue%))+(%minvalue%)
echo "Tmp random: %tmpRandom%"
echo "Random:  %RANDOM%"
ENDLOCAL
Yan
  • 1,569
  • 18
  • 22
1
@(IF not "%1" == "max" (start /MAX cmd /Q /C %0 max&X)ELSE set C=1&set D=2&wmic process where name="cmd.exe" CALL setpriority "REALTIME">NUL)&CLS
:Y
title %random%6%random%%random%%random%%random%9%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%&color %D%&ECHO %random%%C%%random%%random%%random%%random%6%random%9%random%%random%%random%%random%%random%%random%%random%%random%%random%&(IF %C% EQU 46 (TIMEOUT /T 1 /NOBREAK>nul&set C=1&CLS&IF %D% EQU 9 (set D=1)ELSE set /A D=%D%+1)ELSE set /A C=%C%+1)&goto Y

simplified with multiple IF statements and plenty of ((()))

simple
  • 19
  • 1
1

And just to be completely random for those who don't always want a black screen.

@(IF not "%1" == "max" (start /MAX cmd /Q /C %0 max&X)ELSE set A=0&set C=1&set V=A&wmic process where name="cmd.exe" CALL setpriority "REALTIME">NUL)&CLS
:Y
(IF %A% EQU 10 set A=A)&(IF %A% EQU 11 set A=B)&(IF %A% EQU 12 set A=C)&(IF %A% EQU 13 set A=D)&(IF %A% EQU 14 set A=E)&(IF %A% EQU 15 set A=F)
(IF %V% EQU 10 set V=A)&(IF %V% EQU 11 set V=B)&(IF %V% EQU 12 set V=C)&(IF %V% EQU 13 set V=D)&(IF %V% EQU 14 set V=E)&(IF %V% EQU 15 set V=F)
(IF %A% EQU %V% set A=0)
title %A%%V%%random%6%random%%random%%random%%random%9%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%&color %A%%V%&ECHO %random%%C%%random%%random%%random%%random%6%random%9%random%%random%%random%%random%%random%%random%%random%%random%%random%&(IF %C% EQU 46 (TIMEOUT /T 1 /NOBREAK>nul&set C=1&CLS&SET /A A=%random% %%15 +1&SET /A V=%random% %%15 +1)ELSE set /A C=%C%+1)&goto Y

This will change screen color also both are random.

strance
  • 57
  • 3
0

now featuring all the colors of the dos rainbow

@(IF not "%1" == "max" (start /MAX cmd /Q /C %0 max&X)
  ELSE set C=1&set D=A&wmic process where name="cmd.exe" CALL setpriority "REALTIME">NUL)&CLS
:Y
set V=%D%

(IF %V% EQU 10 set V=A) 
    & (IF %V% EQU 11 set V=B)
    & (IF %V% EQU 12 set V=C)
    & (IF %V% EQU 13 set V=D) 
    & (IF %V% EQU 14 set V=E)
    & (IF %V% EQU 15 set V=F)
title %random%6%random%%random%%random%%random%9%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%&color %V%&ECHO %random%%C%%random%%random%%random%%random%6%random%9%random%%random%%random%%random%%random%%random%%random%%random%%random%
&(IF %C% EQU 46 (TIMEOUT /T 1 /NOBREAK>nul&set C=1&CLS&IF %D% EQU 15 (set D=1)ELSE set /A D=%D%+1)
  ELSE set /A C=%C%+1)&goto Y
Nerdroid
  • 13,398
  • 5
  • 58
  • 69
0

here is a example i created for you, it should display a dialog asking you to select a number 1-10, depending on the number you select, it will generate a random number example to a batch file that you named. If you select "1" then you will get a random 1 digit number example. if you select "10" then you will get a random 10 digit number example.

@echo off
color f0
set /p "FileName= Enter Filename (Without Extension) : "
echo @echo off >> %FileName%.bat
echo File Created!
pause
cls
:CommandLine
set /p "calc= ~%ComputerName%: Enter a number to recieve the amount of  random digits :"
if %calc%==genrand_help goto GenerateRandomHelp
if %calc%==1 echo echo %%RANDOM:~-1%% >> %FileName%.bat
if %calc%==2 echo echo %%RANDOM:~-1%%%%RANDOM:~-1%% >> %FileName%.bat 
if %calc%==3 echo echo %%RANDOM:~-1%%%%RANDOM:~-1%%%RANDOM:~-1%% >>  %FileName%.bat
if %calc%==4 echo echo %%RANDOM:~-1%%%%RANDOM:~-1%%%%RANDOM:~-1%%%%RANDOM:~-1%% >> %FileName%.bat
if %calc%==5 echo echo %%Random%% >> %FileName%.bat
if %calc%==6 echo echo %%Random%%%%RANDOM:~-1%% >> %FileName%.bat
if %calc%==7 echo echo %%Random%%%%RANDOM:~-1%%%%RANDOM:~-1%% >> %FileName%.bat 
if %calc%==8 echo echo %%Random%%%%RANDOM:~-1%%%%RANDOM:~-1%%%%RANDOM:~-1%% >> %FileName%.bat
if %calc%==9 echo echo  %%Random%%%%RANDOM:~-1%%%%RANDOM:~-1%%%%RANDOM:~-1%%%%RANDOM:~-1%% >>  %FileName%.bat
if %calc%==10 echo echo %%Random%%%%Random%% >> %FileName%.bat  
goto CommandLine
zask
  • 181
  • 1
  • 6
-1

And just to be completely random, a total lack of order: SET /A V=%random% %%15 +1

@(IF not "%1" == "max" (start /MAX cmd /Q /C %0 max&X)ELSE set C=1&set V=A&wmic process where name="cmd.exe" CALL setpriority "REALTIME">NUL)&CLS
:Y
(IF %V% EQU 10 set V=A)&(IF %V% EQU 11 set V=B)&(IF %V% EQU 12 set V=C)&(IF %V% EQU 13 set V=D)&(IF %V% EQU 14 set V=E)&(IF %V% EQU 15 set V=F)
title %V%%random%6%random%%random%%random%%random%9%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%&color %V%&ECHO %random%%C%%random%%random%%random%%random%6%random%9%random%%random%%random%%random%%random%%random%%random%%random%%random%&(IF %C% EQU 46 (TIMEOUT /T 1 /NOBREAK>nul&set C=1&CLS&SET /A V=%random% %%15 +1)ELSE set /A C=%C%+1)&goto Y