【问题标题】:How do I get truly random numbers in batch?如何批量获得真正的随机数?
【发布时间】:2015-07-06 16:21:36
【问题描述】:

每个人都会在某一时刻使用随机数。所以,我需要从命令提示符生成一些真正的随机数(不是伪随机*),我还需要一个在代码行中生成字母的系统,大小为:set RANDOM=%random% %%2 +1。我只是想抓住一只不存在的蝴蝶吗? *pseudo-random 是随机的,依赖于时间等外部信息,batch 的随机生成器是基于时间的伪随机,为了测试这个打开的 2 个新记事本 .bat 并将这个文件命名为 1.bat
1.蝙蝠

start 2.bat
@echo off
cls
echo %random%
pause

2.bat

@echo off
cls
echo %random%
pause

发生了什么?!?好吧,这是伪随机的,只要打开批处理文件之间没有延迟,批处理文件的编号将是相同的。

【问题讨论】:

标签: windows batch-file random


【解决方案1】:

你基本上是在要求熵池,你的平台是 Windows,对吧?

最好的办法是使用CryptGenRandom()函数,见https://msdn.microsoft.com/en-us/library/windows/desktop/aa379942(v=vs.85).aspx。您可能可以从 Powershell 调用它

更新

显然,有一个用于加密的 .NET 包装器,因此您可以在 Powershell 中使用它

[System.Security.Cryptography.RNGCryptoServiceProvider] $rng = New-Object System.Security.Cryptography.RNGCryptoServiceProvider

$rndnum = New-Object byte[] 4
# Generate random sequence of bytes 
$rng.GetBytes($rndnum)

# rndnum is filled with random bits
....

【讨论】:

  • 它是一个批处理文件,当然它是 WINDOWS!请具体说明它的作用,而不仅仅是提供链接...
  • @EnderScythe 你可能想添加平台标签。关于这个函数,它确实用你认为真正的随机位填充缓冲区。 Windows 平台上非伪随机生成器的最佳选择。我不知道如何从批处理中调用它,但是从 Powershell 调用它可能是一个更好的选择
  • @SeverinPappadeux - 批处理文件标签描述清楚地表明它专门用于 DOS、OS/2 和 Windows。此外,您发布的链接仅提到该函数在 C++ 中工作,因此如果您有办法在 PowerShell 中运行它,请将其添加到您的答案中。
  • @SomethingDark 这正是我的观点。虽然在多个系统上使用批处理文件,但熵/密码随机数生成器是非常特定于平台的。因此,您必须指定您的平台,而不仅仅是batch 标签。请参阅更新 wrt powershell
  • 我们可以只使用 BASIC 批处理,而不是 .net 或 powershell?
【解决方案2】:

在 powershell 上很简单,

您可以单独使用 cmdlet Get-Random 或指定范围,如 1..100 | Get-Random

另一种选择是直接调用System.Random 对象:

$Random = New-Object System.Random
$Random.Next()

【讨论】:

  • System.Random 是通常的伪随机数生成器,而不是问什么
  • 批量随机为 %random%
【解决方案3】:

好吧,您可以编写一个批处理文件版本,其中包含大量生成伪随机数的现有方法之一,或者寻找一个可以在批处理文件中编程而没有其他复杂性的方法,例如The Minimal Standard Random Number Generator,或者更简单的版本,比如Two Fast Implementations,甚至修改其中一个以使其更简单!

@echo off
setlocal EnableDelayedExpansion

rem Pseudo random number generator based on "The Minimal Standard"
rem http://www.firstpr.com.au/dsp/rand31/p87-carta.pdf
rem Antonio Perez Ayala aka Aacini

rem Initialize values
set /A a=16807, s=40

rem APA Modification: use current centiseconds for initial value
for /F "tokens=2 delims=." %%a in ("%time%") do if "%%a" neq "00" set /A s=1%%a %% 100


rem Example of use: generate and show 20 random numbers
for /L %%i in (1,1,20) do (
   call :RandomGen
   echo !rand!
)
goto :EOF



:RandomGen

rem Multiply the two factors
set /A s*=a

rem If the result overflow 31 bits
if %s% lss 0 (
   rem Get result MOD (2^31-1)
   set /A s+=0x80000000
)

rem APA modification: return just the low 15 bits of result (number between 0..32767)
set /A "rand=s & 0x7FFF"

exit /B

当然,我知道这种方法无法与大多数“标准”方法相提并论,但我认为对于简单的批处理文件应用程序,比如游戏来说,它已经足够了......

【讨论】:

  • 技术上是伪随机的......(它使用厘秒)
  • 嗯,这个方法不是“技术上”的伪随机;它是 really 伪随机的(如我的回答中的两行所示)。 This site 表示:仅仅基于确定性计算的“随机数生成器”不能被认为是最纯粹意义上的“真正的”随机数生成器...... 换句话说:有没有办法通过计算机程序生成真实随机数,但是这种方法以非常简单的方式解决了在两个或多个同时批处理文件中生成相同数字序列的问题...
【解决方案4】:

问题确实是 %RANDOM% 只是 伪随机 并且取决于它何时被调用;如果两个脚本同时使用它(more-less),它将具有相同的值。

改为,从您的批处理脚本调用 PowerShell:

    @for /f "tokens=*" %%i in ('powershell -Command "(1..100 | Get-Random)"') do @(
        set "trueRandomInteger_between_1_and_100=%%i"
    )

【讨论】:

    猜你喜欢
    • 2016-09-09
    • 2013-03-08
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多