Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 批处理中的随机生成器_Batch File_Random - Fatal编程技术网

Batch file 批处理中的随机生成器

Batch file 批处理中的随机生成器,batch-file,random,Batch File,Random,我有一个蝙蝠档案 @echo %RANDOM% 并使用命令行执行它 start randomcheck.bat & start randomcheck.bat 打开两个控制台,两个控制台都包含相同的编号4645。这没有达到随机的目的(我只在同时使用随机文件夹时才需要它们)。你是如何批量使用普通随机发生器的 更新 已量化全局种子更新周期。windows shell全局种子每秒更新一次。实际上,我必须增加一秒钟的安全余量,以防止比赛,并希望这是足够的措施。这真糟糕。这意味着为我的iCor

我有一个蝙蝠档案

@echo %RANDOM%
并使用命令行执行它

start randomcheck.bat & start randomcheck.bat
打开两个控制台,两个控制台都包含相同的编号4645。这没有达到随机的目的(我只在同时使用随机文件夹时才需要它们)。你是如何批量使用普通随机发生器的

更新
已量化全局种子更新周期。windows shell全局种子每秒更新一次。实际上,我必须增加一秒钟的安全余量,以防止比赛,并希望这是足够的措施。这真糟糕。这意味着为我的iCore7启动8个进程需要16秒。我仍然不确定这是否成功,因为没有任何官方规定,尽管最初启动了8个进程,但仍有可能发生相对时间偏移,两个进程可能同时完成,我必须注意它们不会再次同时重新启动。这完全是胡说八道,我的问题是,这一批可以在不使用C++或VBScript的情况下固化吗?< /P> < P>随机数生成器在CMD中使用当前时间(第二分辨率)来生成PRNG。因此,在同一秒钟内启动的两个进程将生成相同的“随机”数


对于不会发生冲突的选项,请使用vbscript的随机数生成器(首先随机),或使用guid(您可以通过uuidgen或vbscript生成),或powershell,或……

MC ND在其答案中的所有计数以及后续注释上都是100%正确的

CMD.EXE的每个实例在启动时使用从当前时间派生的种子(分辨率为1秒)初始化随机数生成器。在同一秒内启动的所有CMD.EXE进程将获得相同的随机数序列

另外一个方面-连续秒的初始随机数变化非常缓慢。在我看来,初始随机数实际上可能是从时间中导出的种子值,但我不确定

编辑-我最初是通过实验推断出这一切的。但后来我看到了

下面是一个脚本,演示CMD.EXE的种子如何每秒仅更改一次,并且种子更改非常缓慢:

@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
--产出1--

此脚本演示随机数生成器在单个CMD.EXE进程中“正常”工作

@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
--产出2--

最后,该脚本演示了给定行中的每个
%random%
如何扩展到其自身的值,但行值在循环迭代之间不会更改,因为循环行只解析一次

@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
--产出3--


您可以在一秒钟内启动8个任务,每个任务都会得到自己的随机值

随机数由主任务生成并作为参数发送

setlocal EnableDelayedExpansion
for /L %%n in (1 1 8) DO start task.bat !random!
如果您在task.bat中还需要一个独立的随机生成器,则可以使用该参数作为种子前缀,如

task.bat

setlocal EnableDelayedExpansion
set seed=%1
for /L %%n in ( 1 1 %seed%) do set dummy=!random!

bash中的
$RANDOM
没有此缺陷

@echo win=%RANDOM%

@for /f %%i in ('bash -c "echo $RANDOM"') do @set VAR=%%i

@echo cygwin=%VAR%

当我运行
start randomcheck.bat&start randomcheck.bat
时,打印相同的windows编号,但不同的cygwin编号。使用cygwin比为单个命令编写单独的VBScript要好。也许你可以教我如何用windows脚本主机替代bash-c“echo$RANDOM”,这样就不需要安装cygwin了。

混合批处理Jscript解决方案

@set@e=0/*
@回音
set@e=
cscript//nologo//e:jscript“%~f0”
退出/b
*/
函数getRandomNumber(最小值、最大值){
返回Math.floor(Math.random()*(max-min+1))+min;
}
echo(getRandomNumber(0,10000));

即使是一个完美的随机数生成器也会(最终)产生碰撞。稳健的解决方案必须假设碰撞是可能的,并进行相应的补偿

以下是我过去成功使用的一个策略:

在脚本顶部指定唯一的临时文件名。将
%TIME%
值用于伪“随机”数。将
替换为零,以使字符串对文件名有效。两个进程只有在相隔1/100秒内启动时才会发生冲突(假设您的进程运行时间不超过一天)

你可能会遇到碰撞。可以通过临时锁定文件检测冲突。将脚本的主体放在一个子例程中,并使用重定向到带有“随机”号的锁文件的非标准文件句柄调用主例程-在任何给定时间,只有一个进程可以将输出重定向到锁文件。如果检测到锁,只需返回并重试

@echo off
setlocal

:getUnique

:: Derive a pseudo "unique" name from script name and current time
set "tempBase=%temp%\%~nx0.%time::=%"

:: If you want to test the lock mechanism, uncomment the following
:: line which removes the time component from the "unique" name
::set "tempBase=%temp%\%~nx0.notUnique"

:: Save stderr, then redirect stderr to null
3>&2 2>nul (

  %= Establish lock =%
  9>"%tempBase%.lock" (

    %= Restore stderr and call main routine =%
    2>&3 (call :main %*)

    %= Capture the returned errorlevel if necessary =%
    call set "err=%%errorlevel%%

    %= Force ERRORLEVEL to 0 so that any error detected outside =%
    %= this block must be due to lock failure                   =%
    (call )

  %= Loop back and try again if lock failed due to collision =%
  ) || goto :getUnique
)

:: Delete the temp files and exit with the saved errorlevel
del "%tempBase%*"
exit /b %err%


:main
:: The rest of the script goes here.
:: Additional unique temp file names can be derived from %tempBase% as needed.

:: For this demo, I'll just list the temp file(s) and pause
dir /b "%tempBase%*"
pause

:: Exit with an error for testing purposes
exit /b 1
两个进程不太可能获得相同的唯一名称,但如果它们获得了相同的唯一名称,则第二个进程将检测到冲突,返回并重试,直到成功

如果要测试锁定,请取消对基线的注释。打开两个控制台窗口,并在两个窗口中启动脚本。第一个将成功进入主例程并暂停。第二个将循环,等待第一个完成。按第一个键,第一个将立即结束,第二个将继续进入主程序


如果您想要大于1/100秒的精度,或者如果您的进程可能运行超过一天,那么您应该考虑使用<代码> WMIC OS获取LoalDATECTIMECT/<代码>以获得一个包含日期和时间为1/1000秒的字符串。

是否需要使用<代码>开始<代码>?不如干脆
randomcheck.bat&randomcheck.bat
?@YuriyGalanter为什么我需要同时运行这些进程?事实上,为什么要平行化?但是,让我们先弄清楚为什么一个人首先要运行像
randomcheck.bat这样愚蠢的程序?如果你需要一个好的随机生成器,很可能你需要使用另一种语言。Bat只是一种简单的脚本语言,用于自动化任务等简单目的,而不用于大量计算。我
setlocal EnableDelayedExpansion
set seed=%1
for /L %%n in ( 1 1 %seed%) do set dummy=!random!
@echo win=%RANDOM%

@for /f %%i in ('bash -c "echo $RANDOM"') do @set VAR=%%i

@echo cygwin=%VAR%
@echo off
setlocal

:getUnique

:: Derive a pseudo "unique" name from script name and current time
set "tempBase=%temp%\%~nx0.%time::=%"

:: If you want to test the lock mechanism, uncomment the following
:: line which removes the time component from the "unique" name
::set "tempBase=%temp%\%~nx0.notUnique"

:: Save stderr, then redirect stderr to null
3>&2 2>nul (

  %= Establish lock =%
  9>"%tempBase%.lock" (

    %= Restore stderr and call main routine =%
    2>&3 (call :main %*)

    %= Capture the returned errorlevel if necessary =%
    call set "err=%%errorlevel%%

    %= Force ERRORLEVEL to 0 so that any error detected outside =%
    %= this block must be due to lock failure                   =%
    (call )

  %= Loop back and try again if lock failed due to collision =%
  ) || goto :getUnique
)

:: Delete the temp files and exit with the saved errorlevel
del "%tempBase%*"
exit /b %err%


:main
:: The rest of the script goes here.
:: Additional unique temp file names can be derived from %tempBase% as needed.

:: For this demo, I'll just list the temp file(s) and pause
dir /b "%tempBase%*"
pause

:: Exit with an error for testing purposes
exit /b 1