0

So I've been trying to make the following code:

set /a num1=10
set /a num2=%random% %%60 +%num1%
echo %num2%

(This is simplified)

For this code I need the +%num1% to be a variable because I need to be able to change the lowest number.

For some reason, instead of giving me a random number it gives a totally unrelated number, that isn't random either, but the same every time. My first thought was it was perhaps adding the second variable instead of making a randomizer. That is not the case though, and I'm not sure how to fix this issue.

I have also tried the following code:

set /a num1=10
set /a num2=(%random%*60/32768)+%num1%
echo %num2%

The issue with this code is it never seems to work as randomizer for me even without the variable.

Any help is appreciated.

  • 1
    I think you can apply the answer from here https://stackoverflow.com/a/5777608/2894590 – Okkenator Oct 31 '20 at 17:27
  • Batch is funny, so you might need the spaces and don't use the parens. – Okkenator Oct 31 '20 at 17:30
  • 2
    You should be using `+ num1`, not `+%num1%`. for example `set /a "num2=(%RANDOM% %% 60) + num1"` – Compo Oct 31 '20 at 17:30
  • Also, which version of windows? Since earlier versions work differently. – Okkenator Oct 31 '20 at 17:32
  • @CookieButter I have the latest version of Windows 10... Perhaps I typed it in wrong. Also I believe that may work, I will try it. – Victor Chavez Oct 31 '20 at 18:08
  • `set /a num2=%random% %%60 +%num1%` will introduce a Modulo Bias, this can be accounted for as shown here: https://stackoverflow.com/questions/64624467 Although Note that the accepted solution has a flaw which I pointed out, and fixed, in my answer to this question – Ben Personick Nov 01 '20 at 02:55
  • Also as @CookieButter points out your second form of Random number generation also presents a biased answer which also needs to be accounted for using the question he linked to. – Ben Personick Nov 01 '20 at 02:59
  • @CookieButter thank you for the advice but the post did not help at all. The second method of randomizer does not work at all, nor o any of the modifications or variations mentioned. Also, the randomizer I normally use ``1 set /a num=%random% %%60 +1``` does not seem to work consistantly anymore, and I am not sure why since it has always worked well. It will work properly occassionally then it will have a number much higher than the limits. I am not sure why it's doing this. – Victor Chavez Nov 02 '20 at 03:20

2 Answers2

1

Here's some examples to assist you:

Set "num1=10"
Set /A "num2 = (%RANDOM% %% 60) + num1"
Echo(%num2%
Set "num1=10"
Set /A "num2 = (%RANDOM% * 60 / 32768) + num1"
Echo(%num2%

Please note, that we have only been provided with a very small portion of your batch file, so if this code is part of a parenthesized block, you may need to enable delayed expansion and use !RANDOM! and possibly !num2! instead of %RANDOM% and %num2% respectively.

Compo
  • 36,585
  • 5
  • 27
  • 39
0
  1. In the first form you are have to account for modulus bias, as described further in this question Why do people say there is modulo bias when using a random number generator?

(Note: the accepted answer there has a flaw which I pointed out and provide a solution to in my answer to that question.)

  1. In both the first and the second form they present an incorrect range of values the way it is written. More info can be found here How to use random in BATCH script?

Long story Short:

In both forms, if you want your range to start at 10 and go to 60 you will need to adjust it to be using a modulus of 50, in the first form you must account for modulus bias in your calculations causing some numbers to appear more often.

The first form can be fixed using this method:

SET "Min=10"
SET "Max=60"
SET /A "Discard= 32768 - ( ( ( 32768 %% (Min-Max) ) + 1 ) %% (Min-Max) )"
:Rand
  SET /A "num2=%random%"
  IF %num2% GTR %Discard% GOTO :Rand
SET /A "num2= num2 %% (Min-Max) + Min"
echo=%num2%

The second form can be fixed using this method:

SET "Min=10"
SET "Max=60"
SET /A "num2= %random% * ( Max - Min + 1 ) / 32768 + Min "
echo=%num2%

Example of Full script:

@(SETLOCAL
  ECHO OFF
)

CALL :Main

( ENDLOCAL
  EXIT /B
  pause
)

:Main
  SET "Min=10"
  SET "Max=60"
  SET /A "Discard= 32768 - ( ( ( 32768 %% (Min-Max) ) + 1 ) %% (Min-Max) )"
  ECHO=Form1:
  CALL :Form1
  ECHO=Form2:
  CALL :Form2
  pause

GOTO :EOF

:Form1
  SET "num2=%random%"
  IF %num2% GTR %Discard% GOTO :Form1
  SET /A "num2= num2 %% ( Min - Max ) + Min"
  echo=%num2%
GOTO :EOF

:Form2
  SET /A "num2= %random% * ( Max - Min + 1 ) / 32768 + Min "
  echo=%num2%
GOTO :EOF

Results:

C:\WINDOWS\system32>C:\Admin\SE\testrandom.cmd
Form1:
10
Form2:
31
Press any key to continue . . .

C:\WINDOWS\system32>
Ben Personick
  • 3,074
  • 1
  • 22
  • 29
  • Neither of these worked. I copied and pasted both of them sepretley in their own batch files, and the first always resulted in -40, and the second always resulted in 30. Perhaps I missed something or there is some sort of additional code I need other than the basic ```@echo off``` and ```pause >nul```. Also, is there imperfections in the code ```set /a num2=%random% %%60 +1```. Because I have always used this as a randomizer and it has always worked but recently it has been not functioning. It'll give the proper number 80% of the time but the rest it will give number a bit higher than the max. – Victor Chavez Nov 02 '20 at 03:32
  • @VictorChavez I had used the wrong form, as `%=` doesn't work as expected for this usage. I changed to `SET /A "num2= num2 %% ( Min - Max ) + Min"` which makes the process explicit. I put in the actual cmd script I used to test this as well and resulting output. – Ben Personick Nov 02 '20 at 15:09
  • @VictorChavez as for your statement that `Also, is there imperfections in the code set /a num2=%random% %%60 +1. Because I have always used this` Yes a couple. For one there is a Modulus Bias, for another the range will produce incorrect values using your original code. – Ben Personick Nov 02 '20 at 15:17
  • @VictorChavez As for Part 1, The Modulus Bias, that is to say if you want 1 to 60 you will favor some numbers over others, the amount you favor those numbers depends on size of the range of values you choose to use, however the code presented in this answer accounts for it. You can see more detail about this here: https://stackoverflow.com/a/46991999/3985011 – Ben Personick Nov 02 '20 at 15:17
  • @VictorChavez As for Part 2 as you mentioned `It'll give the proper number 80% of the time but the rest it will give number a bit higher than the max`. Yes this is because you are choosing numbers from 0 to 60 and then adding 10, this is OK if you want your numbers to be between 10 and 70, but not if you want your numbers to be between 10 and 60. This si why the code I presented uses the min and Max variables to make sure the correct min and max are in place. More information on this is found here: https://stackoverflow.com/a/5777608/3985011 – Ben Personick Nov 02 '20 at 15:20