关于c语言中随机数生成连续播种的问题(初学者向)

两年前,大一的寒假,我自学C语言的时候,就碰到了这个问题。一年前,在某处发了一篇科普文章来解释这个问题。如今我觉得有点必要把这个问题放在这里,因为每次都有人在问这个几乎必然会遇到的问题。

先看如下例子:(以中心极限定理为例)
这里写图片描述
这里写图片描述
运行结果为:
这里写图片描述
哈哈,问题就来了,究竟程序出了什么问题导致得到的随机数都是一样的呢?
汗,当时我调试了一个多小时呀(主要是我的程序也犯了同样的错误,但我用另一种方法解决了,周老板的问题却不能用那个办法,柯西呀柯西~)
最后就去请教老师拉,然后就被秒杀了。问题出现在程序第32行的srand(time(NULL))应该放在14行和15行之间!
这就是经常犯的一个错误:重复播种

经过一个下午的分析和学习,我终于大致弄懂了随机数播种的原理,下面将通俗得和大家说说解释解释,求指教:
可以这么说在C语言中的随机数由一个线性同余递推公式 Xn+1=(aXn)+cmodm 得出的。其中播种的种子,即srand(time(NULL))是用来生成一个初值X_0的,递推公式当然有初值才行啦,播种就担当了这个任务。
假设重复播种的话,由于计算机运行速度极快,重复播种导致 X0 都非常接近,以至于随机数都是一样的。#这就是导致出现的随机数都好像一样的原因。经过测试可以知道,time函数的精度大概是50+ms左右,一般这些中心极限定理的模拟程序运行速度快得不行~所以就很难看出得到的随机数的差别了。

那么老师的办法是可行的(当然也是切中要害的)
那么下面我还摸索出两种方法:
1.直接去掉srand(time(NULL)),因为在没有播种的情况下,系统会默认一个种子。
2.由于问题出在时间极短,想办法延长调用srand()的时间即可,我是加头文件windows.h,在循环内加上Sleep(500),即延长500ms(超过了time函数的50+ms的精度),当然产生结果也是合适的伪随机数
关于第二种方法,我产生了这么一个疑问,即使是延迟500ms,种子值得变化并不大,经过查找资料,随机数生成的递推公式为一类线性同余递推式: Xn+1=(aXn)+cmodm
那么问题就来了:第二种方法产生的数是否“随机”呢?
这是一个很好的问题,由于在dos窗口里的数字显示有限(测试发现是200个)那么现在测试循环生产200个随机数。

那么下面将测试一下这个方法的可行性:
1.取延时Sleep(5)时,生产200个随机数导入excel产生的折线图如下,有明显的周期性,而且周期性短
这里写图片描述
2.若取Sleep(300),周期性开始减少,但还是很明显:
这里写图片描述
3.下面分别是Sleep(700),和Sleep(3000)的分布图:
这里写图片描述
这里写图片描述

讲到这里大家应该明白了大概了吧。如果还有不明白的话,可以参考讲随机数讲得惊天地泣鬼神的《计算机程序设计艺术第三卷》

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值