随机数原理

标签: 随机数 原理 | 发表时间:2015-02-01 16:06 | 作者:崔永键
出处:http://www.cuiyongjian.com/
.Net 创建随机数常用的方法:
Random rand = new Random();
Console.WriteLine(rand.Next());

Java中创建随机数的方法:
Random rand = new Random(System.currentTimeMillis());
int i = rand.nextInt();
System.out.println(i);


C/C++中创建随机数的方法:
srand((unsigned)time(NULL)); 
int num = rand();
printf("%d\n",num);



以上随机数的生成原理,基本上是下面这种思路:

比如,我使用线性同余法来自己生成随机数。

class MyRand {
    private int seed;
    public MyRand(int seed) {this.seed = seed;} 
  public int Next()
   {
     int next = (seed * 29 + 37) % 1000;  //线性同余法。
     seed = next;
     return next;
  } 
}

线性同余法:第n+1个数=(第n个数*29+37) % 1000

可见,当你new一个MyRand对象的时候,要给他一个初始的种子seed,然后,这个随机数生成器就会以seed为起始值,开始按照上述公式进行计算,每调用一次Next都会以上次的结果来计算下一个结果。
所以,如果你要生成很多个随机数,请在for循环里面多次调用Next,而不要在for循环里面多次new MyRand对象。
如果在for循环里面每次都new MyRand对象,由于其种子一样,所以你每次调用Next都是输出第一个seed,
也就是说:相同的种子,第一次调用Next都是一样的。
另外,如果你把new MyRand对象写在for循环外面,虽然本次for循环会生成一堆不相同的数。但是当你第二次运行这个程序,由于跟上次启动程序使用的seed相同,所以还是生成一堆跟上次一样的随机数。



于是,你可以在程序中使用Environment.TickCount或者当前时间作为种子,这样每次启动程序,就会创建尽量不同种子的Random对象。


.Net中,你使用new Random()的无参构造函数进行初始化的时候,微软其实是在构造函数里面调用了带int seed这个有参数构造函数,微软给了一个初始化种子,这个种子就是Environment.TickCount(电脑启动后的时间毫秒数)。


所以,要想让程序在2个人跑的时候,产生不同的2堆随机数。请尽可能的让2个人使用不同的随机数种子。解决办法就是把随机数种子设置为系统启动后的一个时间的值。而且为了保证for循环里不会每一波循环都在循环内new Random对象,所以inew Random()这个过程最好放在for循环的外面。

但是,问题也来了,在高并发的程序中(网站),两个用户很可能在同一个毫秒内访问过来,如果你按照毫秒的时间来作为种子给她们生成随机数,那么这俩用户可能种子是相同的,结果导致随机数相同。
所以,针对这种同一个程序被多个用户访问的情况,为了保证同一时间里的用户都产生不同的随机数,只需要保证每个用户来的时候,不要给他重新new Random对象就行。
比如,设置一个全局的静态Random对象,给所有访问来的用户使用,每个用户过来,只需要Next()调用一下产生下一个随机数就可以了。


但是, Random对象不是线程安全的,当大量并发用户来访问的时候,底层Web服务器很可能开辟多个线程来处理请求,结果多个并发线程来访问Random对象调用其Next的时候,导致使用同一个“上一个结果”来计算随机值,结果还是产生了相同的Next值。
所以,这种方案,需要给Random对象加锁,同一时刻只允许一个线程进入临界区。


============真随机==============
上面的随机数产生方法,是有数学原理的,基于多个随机数,通过推测其种子seed,很有可能推测出下一个随机数。所以,为了保证随机数的随机,所以需要seed的随机,seed要想真随机,可以采用获取大自然的一些信息。或者人在操作电脑的时候随机的鼠标动作等等。

在Linux/Unix下可以使用"/dev/random"这个真随机数发生器,它的数据主来来自于硬件中断信息。

Windows:CryptGenRandom()函数,主要依据当前进程Id、当前线程Id、系统启动后的TickCount、当前时间、QueryPerformanceCounter返回的高性能计数器值、用户名、计算机名、CPU计数器的值等等来计算。

当然.Net下也可以使用RNGCryptoServiceProvider 类(System.Security.Cryptography命名空间下)来生成真随机数






相关 [随机数 原理] 推荐:

随机数原理

- - 崔永键的博客
.Net 创建随机数常用的方法:. C/C++中创建随机数的方法:. 以上随机数的生成原理,基本上是下面这种思路:. 比如,我使用线性同余法来自己生成随机数.      int next = (seed * 29 + 37) % 1000;  //线性同余法. 线性同余法:第n+1个数=(第n个数*29+37) % 1000.

Java随机数使用实例总结

- - ITeye博客
Java中提供了好几个类,可以让我们方便的实现随机数等功能,这些类有 java.util.Random, java.util.UUID 以及JDK 7 新引入的 java.util.concurrent.ThreadLocalRandom等. 本文将通过这些类对平时使用的实例进行简单的总结,这些实例的功能大致可以分成四个方面:.

物理学家用激光和钻石创造真随机数

- ArmadilloCommander - Solidot
加拿大渥太华的物理学家Ben Sussman利用激光脉冲和钻石创造了真随机数. 用真随机数编码的信息将难以被黑客破解. Sussman的实验室使用持续几万亿分之一秒的激光脉冲照射钻石,激光进入和出来的方向发生了变化. Sussman称改变与量子真空涨落的相互作用有关,量子力学与大多数物理学法则不同,不可能知道真正发生了什么.

rngd随机数性能问题的解决办法

- -
某产品应用模块在ARM平台上测试时,应用处理业务性能处理表现变差了一些,后台环境上也发现rngd服务进程占用较高,高峰时甚至达到单CPU 100%. 该模块业务代码运行中大量使用了随机数(调用/dev/random获取),会消耗系统随机数熵池. /dev/random产生随机数的原理是利用当前系统的熵池(random pool)来计算出固定一定数量的随机比特,然后将这些比特作为字节流返回.

HandlerSocket的原理

- Roger - MySQLOPS 数据库与运维自动化技术分享
HandlerSocket的应用场景:. MySQL自身的局限性,很多站点都采用了MySQL+Memcached的经典架构,甚至一些网站放弃MySQL而采用NoSQL产品,比如Redis/MongoDB等. 不可否认,在做一些简单查询(尤其是PK查询)的时候,很多NoSQL产品比MySQL要快很多,而且前台网站上的80%以上查询都是简洁的查询业务.

hbase原理

- - CSDN博客云计算推荐文章
1.hbase利用hdfs作为其文件存储系统,利用mapreduce来处理数据,利用zookeeper作为协调工具. 2.行键(row key),类似于主键,但row key是表自带的. 3.列族(column family) ,列(也称作标签/修饰符)的集合,定义表的时候指定的,列是在插入记录的时候动态增加的.

zookeeper原理

- - CSDN博客云计算推荐文章
1.为了解决分布式事务性一致的问题. 2.文件系统也是一个树形的文件系统,但比linux系统简单,不区分文件和文件夹,所有的文件统一称为znode. 3.znode的作用:存放数据,但上限是1M ;存放ACL(access control list)访问控制列表,每个znode被创建的时候,都会带有一个ACL,身份验证方式有三种:digest(用户名密码验证),host(主机名验证),ip(ip验证) ,ACL到底有哪些权限呢.

索引原理

- - ITeye博客
索引是存储引擎用于快速找到记录的一种数据结构. 也就会说索引也是一种数据结构,也占用磁盘空间. 索引是对查询优化最有效的手段,可以将查询提升几个数量级,相当牛掰啊. 1)索引大大减少了服务器需要扫描的数据量. 2)索引可以帮助服务器避免排序和临时表. 3)索引可以将随机IO变为顺序IO. 数据库索引可以想象成一本书的目录,如果想在一本书中找到某个主题,那么先到书的目录中找到这个主题,然后根据目录提供的页码,找到要找的主题.

Hessian原理

- - 互联网 - ITeye博客
Hessian 原理分析. 一.      远程通讯协议的基本原理. 二.      应用级协议 Binary-RPC. Binary-RPC 是一种和 RMI 类似的远程调用的协议,它和 RMI 的不同之处在于它以标准的二进制格式来定义请求的信息 ( 请求的对象、方法、参数等 ) ,这样的好处是什么呢,就是在跨语言通讯的时候也可以使用.

MapReduce原理

- - C++博客-牵着老婆满街逛
       MapReduce 是由Google公司的Jeffrey Dean 和 Sanjay Ghemawat 开发的一个针对大规模群组中的海量数据处理的分布式编程模型. MapReduce实现了两个功能. Map把一个函数应用于集合中的所有成员,然后返回一个基于这个处理的结果集. 而Reduce是把从两个或更多个Map中,通过多个线程,进程或者独立系统并行执行处理的结果集进行分类和归纳.