找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 28853|回复: 8

[数值计算] [讨论]批处理随机数random的bug

[复制链接]
发表于 2010-11-26 15:49:09 | 显示全部楼层 |阅读模式
  大家知道(不知道的现在应该知道了)random是批处理中用来获取随机

数的唯一系统变量,它的随机取值范围是0和32767 之间的任意十进制整数。

不得不说这个random是非常强大的,但是我们今天在这里讨论的不是random

的实际应用(对此论坛已有技术贴进行论述),我们要讨论的是它的bug,

就是它那致命的bug!

  我们先来看下面这个代码:

  1. @echo off
  2. echo %random%
  3. pause>nul
复制代码


  将这段代码保存为test.bat,双击运行黑屏幕上会出现一个随机整数,

没问题呀!真的没问题吗?现在你将这个test.bat连续点击运行10次,记

得记住每次出现的值,你会发现出现的值一次比一次在递增,你们想一下

这是随机取值吗?于是,我又做了下面的测试:

  1. @echo off
  2. set /a n=%1+1
  3. echo %random%
  4. if %n% neq 11 call %0 %n%
  5. pause>nul
复制代码

  
  这是用批来模拟连续10次双击运行test.bat,可是结果却是大不相

同,random又恢复正常了,对此我是没有想明白怎么回事。也许有人会

说可能在一次持续运行中random是会正常的(上面的批可以视为是一次

持续运行)。好的,我们再往下看:

  1. @echo off
  2. for /l %%a in (1,1,10) do echo %random%
  3. pause>nul
复制代码

  1. @echo off
  2. :lp
  3. set /a n+=1
  4. echo %random%
  5. if %n% neq 10 goto lp
  6. pause>nul
复制代码


  同样是一个持续运行过程,用for循环就出现问题了,而goto循环是

正常的,不过我可以告诉大家for循环中的问题是可以解决的,如下:

  1. @echo off&setlocal enabledelayedexpansion
  2. for /l %%a in (1,1,10) do echo !random!
  3. pause>nul
复制代码


    如果有人说是cmd预处理机制做的怪,我也认为是的,但是我还是不

能明白,既然random是系统变量而且是随时改变值的系统变量,这个应

该是不关预处理机制的事的,同样可用下面的代码来小证一下:

  1. @echo off&setlocal enabledelayedexpansion
  2. echo !random!
  3. pause>nul
复制代码


    同样将上面这段代码连续运行10次,这10次得出的随机值居然也是

一样在递增,如果是预处理机制在影响,那么这怎么解释呢?

  也请大家都来就random的bug发表下自己的高见吧。
发表于 2010-11-26 17:24:25 | 显示全部楼层
哈哈,你都说它是个伪军了,我也曾经遇到过这个问题,特别是你在同一时间段,比如1分钟内取若干个随机数,你会看到,它变化较大的是个位、十位、百位,而高位数都没什么变化!~
%random:0,2% 得到的数字要比 %random:-2,2%得到的数字稳定!
发表于 2010-11-26 18:20:18 | 显示全部楼层
计算机就是这么设计的,初始值都是根据一些条件计算得来,然后后面的再继续根据前面的值继续,不过CMD的好像简单了点,没有上次计算值的时候就只根据当前时间来计算,粗略看了下好像是 (CurrentTimeMillis / 1000 * 3 - SomeStaticValue) % 2^15
发表于 2010-11-26 19:44:19 | 显示全部楼层
本来随机数就是,以当前时间开始的:
当前时间 X  一个质数
再和上次的结果运算,或者再加入一些运算,
最后以要得到的最大结果取余,来得到随机数的。

每次的重新打开cmd取得的随机数,因为“上次结果”都是初始值,而只有时间是变动的,
所以,看到了递增,并不奇怪。

for /l %%a in (1,1,10) do echo %random%
这种例子,是先扩展了%random%变量后,才执行for /l语句的,所以结果是一样的。
发表于 2010-11-26 21:04:58 | 显示全部楼层
原谅我单独发帖~~~ ^_^
主要因为自己的主题帖比较少 ~~

我的关于 %random%的探讨:

http://bbs.bathome.net/thread-10146-1-1.html

[ 本帖最后由 vsbat 于 2010-11-26 21:06 编辑 ]
 楼主| 发表于 2010-11-26 21:08:55 | 显示全部楼层

回复 5楼 的帖子

兄弟对论坛有心了,不过这两个贴子确实可以合为一个贴子,可以省点资源不,呵呵。。。
发表于 2010-11-26 21:59:32 | 显示全部楼层
看来batman很久没有搞批处理,忘了不少东西。
%random%、%cd%、%time%等动态变量,在复合语句中使用时尤其要注意适当使用延迟形式。(以前提过多次,特别是在VBT的讨论。现在说的少了,怀念)
好像还有个帖子,batman以为不支持拖放,其实是拖放时一般工作在%UserProfile%目录,而不是脚本所在目录,使用相对路径时要注意。
发表于 2010-11-26 22:12:27 | 显示全部楼层
是不是RANDOM的取值也是类似于TIME也按时间段走动些数值呢?
 楼主| 发表于 2010-11-26 23:20:13 | 显示全部楼层

回复 7楼 的帖子

呵呵,受教,受教—|—
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 01:45 , Processed in 0.019016 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表