Fortran Coder

查看: 308|回复: 4

[讨论] Fortran中所生成的随机数范围

[复制链接]

3

帖子

1

主题

0

精华

新人

F 币
29 元
贡献
12 点
发表于 2018-7-22 13:38:56 | 显示全部楼层 |阅读模式
关于RANDOM_NUMBER函数,Fortran指出他所生成的随机数范围为大于等于0且小于1,如下所述。我编写了一个程序来测试所生成的随机数的范围,发现随机数全部都为大于0且小于1的数,从来没有出现过0,不知道这个说明是不是有问题!!!
与此同时,在我另外一个计算程序里面,随机数竟然出现了1,但是概率较低,不是每次都能出现,请教下大家这是什么问题,不知道大家有没有遇到过这种情况,谢谢!!!
Purpose
Intrinsic Subroutine      Returns a pseudorandom number greater than or equal to zero and less than one from the uniform distribution.
Syntax
CALL RANDOM_NUMBER (harvest)
  
harvest
(Output)  Real. Can be an array. Pseudorandom number, 0?harvest <1, from the uniform distribution, or an array of such numbers.
Remarks
The seed for the pseudorandom number generator used by RANDOM_NUMBER can be set or queried with RANDOM_SEED. If RANDOM_SEED is not used, the processor sets the seed for RANDOM_NUMBER to a processor-dependent value.
All the random procedures (RANDOM_NUMBER, RANDOM, and RAN, and the PortLib functions DRAND, DRANDM, RAND, IRANDM, RAND, and RANDOM) use the same algorithms and thus return the same answers. They are all compatible and can be used interchangeably. (The algorithm used is a 揚rime Modulus M Multiplicative Linear Congruential Generator,?a modified version of the random number generator by Park and Miller in 揜andom Number Generators: Good Ones Are Hard to Find,?CACM, October 1988, Vol. 31, No. 10.)
Compatibility
CONSOLE   STANDARD GRAPHICS   QUICKWIN GRAPHICS   WINDOWS   DLL   LIB
Example
  
      REAL  x, array1 (5, 5)
      CALL RANDOM_SEED()
      CALL RANDOM_NUMBER(x)
      CALL RANDOM_NUMBER(array1)


回复

使用道具 举报

20

帖子

0

主题

0

精华

熟手

F 币
173 元
贡献
75 点

规矩勋章元老勋章新人勋章

发表于 2018-7-22 15:41:52 | 显示全部楼层
单精度浮点,随机到0 的概率是 1/2147483648
双色球中奖概率为 1/17720000
前者大概是后者的  1/121
天之道,损有余而补不足

3

帖子

1

主题

0

精华

新人

F 币
29 元
贡献
12 点
 楼主| 发表于 2018-7-22 15:57:03 | 显示全部楼层
胡文刚 发表于 2018-7-22 15:41
单精度浮点,随机到0 的概率是 1/2147483648
双色球中奖概率为 1/17720000
前者大概是后者的  1/121 ...

只要有出现的概率,当次数达到一定程度后,总应该出现一次吧,那个程序我运行了24h,次数肯定够了,但是却没有过一次。

1290

帖子

12

主题

5

精华

论坛跑堂

Fcode跑堂伙计

F 币
43 元
贡献
152 点

新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

发表于 2018-7-23 17:18:32 | 显示全部楼层
不是这么计算的。正确的计算方法是:

落入 [0.0,0.1) 概率为 0.1
落入 [0.1,0.2) 概率为 0.1
落入 [0.2,0.3) 概率为 0.1
...
落入 [0.9,1.0) 概率为 0.1
(总和为 1),平均每10次可以得到一次。

在第一种可能中,
落入 [0.00,0.01) 概率为 0.01
落入 [0.01,0.02) 概率为 0.01
落入 [0.02,0.03) 概率为 0.01
...
落入 [0.09,0.10) 概率为 0.01
(总和为0.1),平均每100次可以得到一次

所以,
落入 [0,1.0e-38) 的概率为 1/1.0e-38,平均 10e38 次可以得到一次 0
而不是 2147483648

PS:我这里用十进制来计算,实际应该按二进制来计算。也就是落入 [0,0.5) , [0.5,1.0)  的概率,以及 [0,0.25) [0.25,0.5) [0.5,0.75) [0.75,1.0) 的概率,这样算下去。算法不同,结果一致。

你确定你计算了 10e38 次吗?
按24小时来计算,你的运算能力要达到每 1.1574073E+33 次,才可能在理想情况下得到1次0


1290

帖子

12

主题

5

精华

论坛跑堂

Fcode跑堂伙计

F 币
43 元
贡献
152 点

新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

发表于 2018-7-23 17:32:30 | 显示全部楼层
你可以用以下代码测试一下概率。

[Fortran] 纯文本查看 复制代码
Program Main
  real :: a
  integer(8) :: i = 0_8 , j
  integer(8) :: ddc(38) = 0
  call RANDOM_SEED()
  do
    call RANDOM_NUMBER(a)
    j = int(-log10(a)) + 1
    ddc(j) = ddc(j) + 1
    i = i + 1_8
    if( mod(i,100000000_8) == 0_8 ) then
      write(*,'("Total:",g0)') i
      write(*,'(*(5i16,/))') ddc
      write(*,'("check:",g0)') sum(ddc)
    end if
  end do  
  read(*,*) 
End Program Main


这个代码用来统计,N次取随机数的结果,其结果各数量级的个数,也就是 0.1以内的个数,0.01以内的个数,0.001以内的个数...
当 N 足够大时,个数之间的比例大约是
0.9 , 0.09 , 0.009 .... 加起来约等于 1

如图:
0.9.jpg

也就是说,我算了 20亿次,才得到一个 e-10 次方数量级的数。
你要想得到 0 ,你需要大约10次得到 e-38 次方数量级的数的机会。
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

QQ|捐赠本站|Archiver|关于我们 About Us|群聊|Fcode

GMT+8, 2018-10-17 00:20

Powered by Discuz! X3.2

© 2001-2017 Comsenz Inc.

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