skip to Main Content

(Because someone asked, I have Windows 10, if anyone was wondering.

I have recently been working on a desktop PAI (Partial Artificial Intelligence) that will be able to perform some basic tasks for me while I am not at my computer.

However, I want it to choose and say 1 of 9 different possible messages. For example, I have 9 different ways to say “How can I help you?”, and I want it to choose and echo one of those 9 ways.

To do this, I want to use the variable %RANDOM%. The problem is that %RANDOM% generates a random number in between 0 and 32767, and I only want it to generate a random number in between 1 and 9.

I have seen multiple people across the internet say to use the piece of code:

 SET /a rand=(%RANDOM%*9/32768)+1 

However, this does not work. Or maybe it does for some people, but certainly not for me. Whenever I implement this into a batch file, it either just closes the window because it doesn’t know how to run the code, or it just chooses the same number over and over again, no matter what.

I have also already tried it with and without Delayed Expansion, and if I try to run the code in the regular command prompt (CMD.EXE), it just says “Missing operator.”

It’s hard for me because I don’t really know much about arithmetic in batch. Any help on fixing this is greatly appreciated!

2

Answers


  1. What happens if you use set /a rnd=(%RANDOM%%%9)+1 instead?

    Example:

    @Echo Off
    
    Set "msg[1]=G'day!"
    Set "msg[2]=Hello!"
    Set "msg[3]=Hey!"
    Set "msg[4]=Hi!"
    Set "msg[5]=Hiya!"
    Set "msg[6]=Howdy?"
    Set "msg[7]=Sup?"
    Set "msg[8]=Whazzup?"
    Set "msg[9]=Yo!"
    
    Set /A rnd=(%RANDOM% %% 9) + 1
    
    Call Echo %%msg[%rnd%]%%
    
    Pause
    
    Login or Signup to reply.
  2. When you state that you constantly get the same value when you run your script, I suspect you are launching your script by double clicking the script within Windows Explorer, or else on your desktop.

    The source of that problem is the random seed value that each cmd.exe session establishes upon startup. The seed changes by 3 or 4 only once every second, (10 every 3 seconds).

    Each time you launch your script by double clicking, you start a new cmd.exe session. All sessions that launch within the same second will be given the exact same random seed, and thus the same sequence.

    Your problem is compounded by the formula you use to generate a “random” number from 1 to 9: SET /a "rand=(%RANDOM%*9/32768)+1" With that formula the initial result will change only once every ~18 minutes.

    A simpler formula of set /a "rand=%random% %% 9 + 1" will change the initial value once every second.

    Here is a demonstration of what I mean.

    test.bat

    @echo off
    set "t=%time%
    set /a r=%random%, n1=r*9/32768+1, n2=r%%9+1
    echo t=%t%, r=%r%, n1=%n1%, n2=%n2%
    

    Here is what happens when I use a loop to run the script 25 times in different cmd.exe sessions:

    C:test>for /l %n in (1 1 25) do @cmd /c test.bat
    t=14:22:05.00, r=29206, n1=9, n2=2
    t=14:22:05.13, r=29206, n1=9, n2=2
    t=14:22:05.24, r=29206, n1=9, n2=2
    t=14:22:05.35, r=29206, n1=9, n2=2
    t=14:22:05.47, r=29206, n1=9, n2=2
    t=14:22:05.58, r=29206, n1=9, n2=2
    t=14:22:05.71, r=29206, n1=9, n2=2
    t=14:22:05.83, r=29206, n1=9, n2=2
    t=14:22:05.96, r=29206, n1=9, n2=2
    t=14:22:06.08, r=29209, n1=9, n2=5
    t=14:22:06.19, r=29209, n1=9, n2=5
    t=14:22:06.32, r=29209, n1=9, n2=5
    t=14:22:06.44, r=29209, n1=9, n2=5
    t=14:22:06.55, r=29209, n1=9, n2=5
    t=14:22:06.66, r=29209, n1=9, n2=5
    t=14:22:06.79, r=29209, n1=9, n2=5
    t=14:22:06.90, r=29209, n1=9, n2=5
    t=14:22:07.02, r=29212, n1=9, n2=8
    t=14:22:07.15, r=29212, n1=9, n2=8
    t=14:22:07.27, r=29212, n1=9, n2=8
    t=14:22:07.38, r=29212, n1=9, n2=8
    t=14:22:07.50, r=29212, n1=9, n2=8
    t=14:22:07.63, r=29212, n1=9, n2=8
    t=14:22:07.74, r=29212, n1=9, n2=8
    t=14:22:07.86, r=29212, n1=9, n2=8
    

    t is the time, r is the raw random seed value, n1 is the value computed by your original formula, and n2 is the value with the simpler formula. You can see that your original formula result never changes, even though the seed value changed 3 times.

    If I repeat the experiment, but this time run each command within the same cmd.exe session, then you see that the random number sequence is reasonable.

    C:test>for /l %n in (1 1 25) do @test.bat
    t=14:26:12.83, r=24169, n1=7, n2=5
    t=14:26:12.83, r=7515, n1=3, n2=1
    t=14:26:12.84, r=8502, n1=3, n2=7
    t=14:26:12.84, r=11715, n1=4, n2=7
    t=14:26:12.86, r=28979, n1=8, n2=9
    t=14:26:12.86, r=5966, n1=2, n2=9
    t=14:26:12.86, r=4269, n1=2, n2=4
    t=14:26:12.87, r=27310, n1=8, n2=5
    t=14:26:12.87, r=11966, n1=4, n2=6
    t=14:26:12.89, r=16129, n1=5, n2=2
    t=14:26:12.89, r=16597, n1=5, n2=2
    t=14:26:12.89, r=2994, n1=1, n2=7
    t=14:26:12.90, r=16762, n1=5, n2=5
    t=14:26:12.90, r=1718, n1=1, n2=9
    t=14:26:12.92, r=17976, n1=5, n2=4
    t=14:26:12.92, r=20805, n1=6, n2=7
    t=14:26:12.94, r=11730, n1=4, n2=4
    t=14:26:12.94, r=20414, n1=6, n2=3
    t=14:26:12.94, r=28978, n1=8, n2=8
    t=14:26:12.95, r=11615, n1=4, n2=6
    t=14:26:12.95, r=13486, n1=4, n2=5
    t=14:26:12.97, r=21228, n1=6, n2=7
    t=14:26:12.97, r=25754, n1=8, n2=6
    t=14:26:12.97, r=3979, n1=2, n2=2
    t=14:26:12.98, r=16189, n1=5, n2=8
    

    There really isn’t a good pure batch solution for randomly generating numbers across different cmd.exe sessions. But you can use hybrid scripting to get a decent solution. Below is a demonstration JScript/batch solution that works well. However it is slow because the :random function must initialize a new CSCRIPT session each time it is called.

    test2.bat

    @if (@X)==(@Y) @end /* harmless hybrid line that begins a JScrpt comment
    :::::::::::: batch portion ::::::::::::::
    @echo off
    call :random 1 9 rand
    echo %rand%
    exit /b
    
    :random  min  max  rtnVar
    for /f %%A in (
      'cscript //E:JScript //nologo "%~f0" "Math.floor(Math.random()*(%2-%1+1))+%1"'
    ) do set "%3=%%A"
    exit /b
    
    
    :: The following JScript code evaluates a JScript expression
    :: and writes the result to stdout
    ************ JScript portion *********************/
    WScript.StdOut.WriteLine(eval(WScript.Arguments.Unnamed(0)));
    

    Here are results of rapidly running the above in 25 different cmd.exe sessions – exactly the result you want.

    C:test>for /l %n in (1 1 25) do @cmd /c test2.bat
    9
    8
    7
    5
    9
    8
    5
    1
    5
    6
    5
    8
    7
    8
    7
    1
    2
    6
    6
    5
    6
    4
    8
    4
    9
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search