返回列表 发帖

[数值计算] 批处理生成指定范围内的随机数

:rndnum
set lnum=%~1
set unum=%~2
if "%lnum%" == "" (set lnum=1)
if "%unum%" == "" (set unum=9)
if %lnum% GTR %unum% (set lnum=%unum%&set unum=%lnum%)
set /a rnd=(%unum% - %lnum% + 1) * %random% / 32768 + %lnum%
goto :eofCOPY
其中%random%的范围为0-32767,那么这个随机小数就可以通过除以32768获得,剩下的取整不需要人工干预,批处理就自动解决了。

生成随机数的范围:大于等于最小值,小于等于最大值

为了确定是否稳定,测试了10W次
测试代码如下:
@echo off
setlocal ENABLEDELAYEDEXPANSION
:s
cls
for /l %%a in (1,1,100000) do (
call :rndnum
echo. %%a 中间结果:!rnd!
if 1!rnd! GTR 19 (call :over !rnd!)
if 1!rnd! LSS 11 (call :over !rnd!)
)
echo.
echo.
echo.计算结束!
echo.
echo.
pause
exit
:rndnum
set lnum=%~1
set unum=%~2
if "%lnum%" == "" (set lnum=1)
if "%unum%" == "" (set unum=9)
if %lnum% GTR %unum% (set lnum=%unum%&set unum=%lnum%)
set /a rnd=(%unum% - %lnum% + 1) * %random% / 32768 + %lnum%
goto :eof
:over
cls
echo.
echo.
echo. 调试结果:%~1
echo.
echo.
pause
goto :eofCOPY
1

评分人数

当一个人不断追问的时候,其实就已经对自己产生了怀疑

不用这么复杂吧,比如:15至41之间的随机数
set /a w=%random%%%27+15
技术问题请到论坛发帖求助!

TOP

回复 2楼 的帖子

可能楼主的意思是要把这个功能给函数化吧。
但我觉得函数里面不必做那么多容错处理,在函数说明里面写清楚如何调用就行了,如果用户不按照正确的方法来调用,那就活该他出错了。
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

其实关键的就这一句,常做软件开发的应该都知道,这个是生成指定范围内随机数的公式
只不过那个0-1之间的随机小数通过%random%/32768生成。

set /a rnd=(%unum% - %lnum% + 1) * %random% / 32768 + %lnum%COPY


这个做成函数了,使用 call :rndnum 最小值 最大  调用,若不传参数,默认生成1-9之间的随机数
当一个人不断追问的时候,其实就已经对自己产生了怀疑

TOP

回复 4楼 的帖子

批处理中,/表示整除,请问你的“随机小数”是如何生成的呢?我咋没看到小数点呢?
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

回复 5楼 的帖子

batchar你回答的干吗那么幽默啊。呵呵

TOP

回复 5楼 的帖子

在P中,计算顺序是先算括号,然后按照优先级从左往右计算

这样,上面的
set /a rnd=(%unum% - %lnum% + 1) * %random% / 32768 + %lnum%COPY
1。算括号里面的加减
2。然后是乘以随机数
3。再计算除法,这样生成的就是个整数,范围在最大数和0之间

4。此时加上最小数,范围就被定下来了。

这个算法变相取得了随机小数,呵呵。
另外,这个32768个人感觉有点不对劲,貌似应该是32767,这样结果才不会偏小。
看了看随机数的范围,越看越觉得应该是32767。大家再研究吧,呵呵

[ 本帖最后由 qq362220083 于 2009-3-31 14:51 编辑 ]
当一个人不断追问的时候,其实就已经对自己产生了怀疑

TOP

回复 7楼 的帖子

你说的“随机小数”是指随机的比较小的整数,而不是随机小数,是这样吗?
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

头大!!!
set /a rnd=(%unum% - %lnum% + 1) * %random% / 32768 + %lnum%COPY
中,按照咱们平时的随机数,应该是像下面这样
set /a rnd=(%unum% - %lnum% + 1) * (%random% / 32768) + %lnum%COPY
但由于乘法和除法处于同一优先级,因此,先计算除法和先计算乘法的结果一样。这个是理论上的。
但是,在批处理中,无法计算小数,批处理会把结果中的小数直接舍掉。若按照正常的计算顺序,会造成结果永远都是最小值,因为
%random% / 32768COPY
永远是0-1之间的小数,批处理总是舍掉小数变成0,任何数乘以0结果不用我重复吧

因此我就按照数学上的四则运算法则,把计算顺序变为先计算乘法,后计算除法,这样的结果同样会被批处理省略掉小数,但这却正好帮了忙,省去了最后取整的过程。

还有,这个随机结果会比正常结果偏小0.5左右,理论上的。我想大家不需要那么精确吧,呵呵

另外,Batcher,你要是还不明白,我就无能为力了,真的怀疑你的小学数学老师。。。

[ 本帖最后由 qq362220083 于 2009-4-10 05:19 编辑 ]
当一个人不断追问的时候,其实就已经对自己产生了怀疑

TOP

回复 9楼 的帖子

以我的智商,只能做出8楼的理解,无法达到你那样的认知境界,实在是惭愧啊。
9楼的讲解很好,嗯,我在大约两年前也给别人讲过类似的内容。
噢,对了,千万别忘记替我向你的小学数学老师们致以崇高的敬意,他们培养出了这么优秀的学生,真实羡煞旁人呐。
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

好久没来了,今天来转转,看到这个帖子。呵呵,心里有点感触了。。。


使用%random%取得的随机数范围在0 和 32767之间

%random% / 32767  就是范围在0-1之间的小数

但是批处理中,对于数学运算,若结果是小数,则自动忽略小数,只取结果中的整数部分

因此%random% / 32768在批处理中只会得到0

但四则运算法则中,乘法和除法是同一优先级,同样批处理也遵守。所以,可以乘以一个随机整数,然后除以随机整数的最大值,得到一个随机范围在0与(最大值-最小值)之间的整数。最后加上最小值!

例子:

得到1-10之间的随机数
1:10 - 1 + 1 =10
2:10 * %random%    返回的是0~327670之间的整数
3:(0~327670)/32768    返回的是0~9之间的整数,算术的最小值最大值的获取方法分别是用范围的最小值和最大值除以32768,得到的分别是算术的最小值和最大值
4:加上最小值1,返回的是1~10

[ 本帖最后由 qq362220083 于 2010-3-16 17:25 编辑 ]
当一个人不断追问的时候,其实就已经对自己产生了怀疑

TOP

嗯,楼主解释非常清楚了,不过例子的思路让人感到有点复杂。

TOP

呵呵 看了楼上这么多详细的解释,我说下我的看法
依据那个公式可以将产生确定范围的随机数的方法分解成以下几步:
1.确定范围:max-min+1
2.扩大这个范围max-min+1)*%random%   
3.再缩小范围:(max-min+1)*%random%/32768 这样就产生了0~max-min+1之间的范围
4最后来个平移:(max-min+1)*%random%/32768+min 这样就产生了min~max之间的随机数了
疑问:这种方法跟%random%%%max+min是否存在不同之处?望高手指点下

TOP

贴个除法函数吧
@echo off
setlocal enabledelayedexpansion
call :_div %RANDOM% 32768
echo %quo%
call :_div %RANDOM% 32768
echo %quo%
call :_div %RANDOM% 32768
echo %quo%
call :_div %RANDOM% 32768
echo %quo%
call :_div %RANDOM% 32768
echo %quo%
call :_div %RANDOM% 32768
echo %quo%
call :_div 32767 32768
echo %quo%
goto :eof
rem 除法子程序开始
:_div
  if "%1"=="" (echo 请输入被除数(参数 %%^1)&goto :EOF)
  if "%2"=="" (echo 请输入除数(参数 %%^2)&goto :EOF)
  set /a Maxd=2147483647, scp=0, ded=%1, dvr=%2&set quo=
  if %dvr% equ 0 (echo 错误,除数为零!&goto :EOF)
  if %ded% equ 0 (set quo=0&goto :EOF)
  if "%ded%"=="%1" (
    if not "%dvr%"=="%2" echo 参数 %%^2 输入错误或数值超限&goto :EOF
  ) else (
    echo 参数 %%^1 输入错误或数值超限
    if not "%dvr%"=="%2" echo 参数 %%^2 输入错误或数值超限&goto :EOF
  )
  :divbg
  set /a quo=%ded%/%dvr%, rdd=quo*dvr
  if %rdd% neq %ded% (
    if %ded% leq %Maxd:~0,-1% (
      set ded=%ded%0&set /a scp+=1&goto :divbg
    )
  )
  if %quo% equ 0 goto :EOF
  if %scp% neq 0 (
    if "!quo:~-%scp%!"=="!quo!" (
      set quo=00000000%quo%&set quo=0.!quo:~-%scp%!
    ) else (
      set quo=!quo:~0,-%scp%!.!quo:~-%scp%!
    )
  )
goto :EOF
rem End_divCOPY

TOP

这个确实很好用……
set a=(!random!+1)%%(!ramdom!+1)

TOP

返回列表