Random generator in the batch

MC ND is 100% correct on all counts within his answer, and also his follow-on comment.

Each instance of CMD.EXE initializes the random number generator upon startup using a seed that is derived from the current time with 1 second resolution. All CMD.EXE processes that launch within the same second will get identical random number sequences.

One additional aspect – the initial random number for consecutive seconds changes very slowly. It looks to me like the initial random number may actually be the seed value that was derived from the time, but I’m not sure.

EDIT – I had originally deduced all of this via experimentation. But I have since seen confirmation from an authoritative source.

Here is a script that demonstrates how the seed for CMD.EXE changes only once per second, and the seed changes very slowly:

@echo off
setlocal
set "last=%time:~9,1%"
for /l %%N in (1 1 30) do (
  call :wait
  cmd /c echo %%time%% %%random%% %%random%% %%random%% %%random%% %%random%% %%random%%
)
exit /b

:wait
if %time:~9,1% equ %last% goto :wait
set "last=%time:~9,1%"
exit /b

— OUTPUT 1 —

22:13:26.31 30024 16831 1561 8633 8959 14378
22:13:26.41 30024 16831 1561 8633 8959 14378
22:13:26.51 30024 16831 1561 8633 8959 14378
22:13:26.61 30024 16831 1561 8633 8959 14378
22:13:26.71 30024 16831 1561 8633 8959 14378
22:13:26.81 30024 16831 1561 8633 8959 14378
22:13:26.91 30024 16831 1561 8633 8959 14378
22:13:27.01 30027 27580 19425 32697 19274 18304
22:13:27.11 30027 27580 19425 32697 19274 18304
22:13:27.21 30027 27580 19425 32697 19274 18304
22:13:27.31 30027 27580 19425 32697 19274 18304
22:13:27.41 30027 27580 19425 32697 19274 18304
22:13:27.51 30027 27580 19425 32697 19274 18304
22:13:27.61 30027 27580 19425 32697 19274 18304
22:13:27.71 30027 27580 19425 32697 19274 18304
22:13:27.81 30027 27580 19425 32697 19274 18304
22:13:27.91 30027 27580 19425 32697 19274 18304
22:13:28.01 30030 5560 4521 23992 29588 22231
22:13:28.11 30030 5560 4521 23992 29588 22231
22:13:28.21 30030 5560 4521 23992 29588 22231
22:13:28.31 30030 5560 4521 23992 29588 22231
22:13:28.41 30030 5560 4521 23992 29588 22231
22:13:28.51 30030 5560 4521 23992 29588 22231
22:13:28.61 30030 5560 4521 23992 29588 22231
22:13:28.71 30030 5560 4521 23992 29588 22231
22:13:28.81 30030 5560 4521 23992 29588 22231
22:13:28.91 30030 5560 4521 23992 29588 22231
22:13:29.01 30033 16308 22385 15287 7135 26158
22:13:29.11 30033 16308 22385 15287 7135 26158
22:13:29.21 30033 16308 22385 15287 7135 26158

This script demonstrates that the random number generator works “properly” within a single CMD.EXE process.

@echo off
setlocal enableDelayedExpansion
set "last=%time:~9,1%"
for /l %%N in (1 1 30) do (
  call :wait
  echo !time! !random! !random! !random! !random! !random! !random!
)
exit /b

:wait
if %time:~9,1% equ %last% goto :wait
set "last=%time:~9,1%"
exit /b

— OUTPUT 2 —

22:16:10.30 24175 26795 4467 2450 12031 9676
22:16:10.40 6873 17221 14201 17898 32541 29918
22:16:10.50 700 21044 25922 8616 24057 7657
22:16:10.60 25370 6519 26054 28443 4865 1931
22:16:10.70 26989 9396 12747 26808 6282 32182
22:16:10.80 22778 11460 11989 26055 10548 1809
22:16:10.90 4668 27372 30965 12923 5941 16533
22:16:11.00 23426 11396 24402 29658 5150 11183
22:16:11.10 1557 13572 18815 21801 4103 23119
22:16:11.20 3459 30126 20484 32750 3360 16811
22:16:11.30 14041 26960 31897 24736 16657 1954
22:16:11.40 5112 18377 30475 18837 12216 10237
22:16:11.50 13136 6241 27074 29398 8996 9738
22:16:11.60 16027 15122 13659 28897 4827 29753
22:16:11.70 27502 8271 11489 21888 16590 7886
22:16:11.80 30405 25582 7288 5432 7310 26557
22:16:11.90 202 11076 23205 20739 28053 12621
22:16:12.00 4234 20370 10355 5974 27590 8732
22:16:12.10 24411 21836 16161 24731 22898 10378
22:16:12.20 23060 17903 10788 19107 29825 15561
22:16:12.30 6772 1371 674 13257 15504 18422
22:16:12.40 1344 31971 23977 8630 10789 15367
22:16:12.50 18945 17823 20691 10497 5958 31613
22:16:12.60 18294 10398 26910 8744 21528 272
22:16:12.70 25603 9991 24084 11667 16977 5843
22:16:12.80 19405 5457 16285 11165 26783 10627
22:16:12.90 20041 31763 26390 11994 19285 12287
22:16:13.00 21342 13853 9336 24080 2555 2067
22:16:13.10 9328 30429 1722 2211 22934 24871
22:16:13.20 8168 21818 19125 11102 449 8813

Finally, this script demonstrates how each %random% within a given line expands to its own value, but the line values don’t change between loop iterations because the looped line is only parsed once.

@echo off
setlocal
set "last=%time:~9,1%"
for /l %%N in (1 1 30) do (
  call :wait
  echo %time% %random% %random% %random% %random% %random% %random%
)
exit /b

:wait
if %time:~9,1% equ %last% goto :wait
set "last=%time:~9,1%"
exit /b

— OUTPUT 3 —

22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157
22:20:10.98 28188 30311 32299 7392 5874 32157

Leave a Comment