黑马程序员技术交流社区

标题: 随机数的小问题 [打印本页]

作者: 何丛    时间: 2013-9-25 21:47
标题: 随机数的小问题
本帖最后由 何丛 于 2013-9-25 23:50 编辑
  1. public static void main(String[] args) {
  2.          Random r1 = new Random(100);
  3.      Random r2 = new Random(100);
  4.      System.out.println("r1:"+r1.nextInt());
  5.      System.out.println("r2:"+r2.nextInt());
  6.      Random r = new Random();
  7.      System.out.println("r:"+r.nextInt());
  8. }
复制代码
两次运行的结果
        
图一                        

图二

既然是随机数,为什么r1,r2多次运行的结果一样的?是因为种子吗?那么种子的作用又是什么?


作者: 罗凯健    时间: 2013-9-25 21:51
伪随机数,不是真正的随机数。是用算法算出来的,这是毕老师说的
作者: 何丛    时间: 2013-9-25 21:55
罗凯健 发表于 2013-9-25 21:51
伪随机数,不是真正的随机数。是用算法算出来的,这是毕老师说的

我不太同意你的看法,
虽然是伪随机数,但也是可以获取随机数

作者: 黑马戴帅军    时间: 2013-9-25 22:00
多次调用出相同序列,是因为 Random randdom = new Random(); 这个地方,随机数种子是当前的时间,由于你循环调用时时间很短,随机种子一样,才出现重复序列,这个是取随机数的方法的问题,稍微改动一下取随机数的方法就可以得到不重复的序列(可以在写一个方法,如果这个数字在 hashtable中有了,就不生成这个数,如果没有这个数,则输出)这个和算法本身没有太大关系。
作者: 梁贺    时间: 2013-9-25 22:12
API中的解释:
Random类的实例用于生成伪随机数流。此类使用 48 位的种子,使用线性同余公式 (linear congruential form) 对其进行了修改(请参阅 Donald Knuth 的The Art of Computer Programming, Volume 3,第 3.2.1 节)。

如果用相同的种子创建两个 Random 实例,则对每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列。为了保证此属性的实现,为类 Random 指定了特定的算法。为了 Java 代码的完全可移植性,Java 实现必须让类 Random 使用此处所示的所有算法。但是允许 Random 类的子类使用其他算法,只要其符合所有方法的常规协定即可。
所以是用相同的种子创建Random实例,而随机数种子是当前的时间,在CPU高速运行下,随机种子一般还没改变就创建了Randon实例,所以输出的一样。

希望能帮助你~
作者: 王靖远    时间: 2013-9-25 22:15
种子相同,在不同的机器上算出来也是一样的结果。想结果不同,用不同的种子。可以取当前时间作为种子
作者: 罗凯健    时间: 2013-9-25 22:19
何丛 发表于 2013-9-25 21:55
我不太同意你的看法,
虽然是伪随机数,但也是可以获取随机数

说的在理,于是我专门去百度了一下。自己也试了一下,设置了种子的也是随机数,但是这个随机数是根据种子算出来,假如调用Random的setseed方法(代替构造方法传入种子)不传入参数的话默认是传入系统时钟。与执行时间无关。因为我在Print了r1之后让线程sleep了1秒结果打印r2还是同一个数字。不设种子每次获得的随机数都不同,大概就是这样,原理嘛查JDK也没说。

作者: 暮雨    时间: 2013-9-25 22:21
是啊,你的是把种子写死了的缘故,看下java 类库源代码
  1. /**
  2.      * Creates a new random number generator using a single {@code long} seed.
  3.      * The seed is the initial value of the internal state of the pseudorandom
  4.      * number generator which is maintained by method {@link #next}.
  5.      *
  6.      * <p>The invocation {@code new Random(seed)} is equivalent to:
  7.      *  <pre> {@code
  8.      * Random rnd = new Random();
  9.      * rnd.setSeed(seed);}</pre>
  10.      *
  11.      * @param seed the initial seed
  12.      * @see   #setSeed(long)
  13.      */
  14.     public Random(long seed) {
  15.         this.seed = new AtomicLong(0L);
  16.         setSeed(seed);
  17.     }
复制代码
在这里你把参数seed写死了的,所以结果你懂的,一般用无参构造的就行,在java类库源代码中式这样定义的
  1. /**
  2.      * Creates a new random number generator. This constructor sets
  3.      * the seed of the random number generator to a value very likely
  4.      * to be distinct from any other invocation of this constructor.
  5.      */
  6.     public Random() { this(++seedUniquifier + System.nanoTime()); }
  7.     private static volatile long seedUniquifier = 8682522807148012L;
复制代码
这样取出的每次的seed就会不一样,才能生成随机数,我把代码改了一下,
  1. import java.util.Random;


  2. public class Test1{
  3.     public static void main(String[] args) {
  4.         Random r1 = new Random();
  5.             Random r2 = new Random();
  6.             System.out.println("r1:"+r1.nextInt(10));
  7.             System.out.println("r2:"+r2.nextInt(25));
  8.             Random r = new Random();
  9.             System.out.println("r:"+r.nextInt(100));
  10.     }
  11. }
复制代码
这样就可以生成随机数
希望能帮到你
作者: 暮雨    时间: 2013-9-25 22:23
黑马戴帅军 发表于 2013-9-25 22:00
多次调用出相同序列,是因为 Random randdom = new Random(); 这个地方,随机数种子是当前的时间,由于你循 ...

哥们,错了吧,不是调用时间短,是因为他把随机数种子写死了。

作者: 暮雨    时间: 2013-9-25 22:25
梁贺 发表于 2013-9-25 22:12
API中的解释:
Random类的实例用于生成伪随机数流。此类使用 48 位的种子,使用线性同余公式 (linear congr ...

说得好,不过说错了。

作者: 梁贺    时间: 2013-9-25 22:38
暮雨 发表于 2013-9-25 22:25
说得好,不过说错了。

好吧,没看源码,一直以为是当前时间作为种子的。又有收获了~!
作者: 暮雨    时间: 2013-9-25 22:45
梁贺 发表于 2013-9-25 22:38
好吧,没看源码,一直以为是当前时间作为种子的。又有收获了~!

我现在是打个呵呵都得输验证码

作者: 梁贺    时间: 2013-9-25 22:48
一样 貌似是中级之后都得输验证码。以后有时间的打算多看看源码,不能辜负了Java的开源嘛!
作者: 何丛    时间: 2013-9-25 23:48
多谢各位的解答
作者: chensc    时间: 2013-9-26 08:37
学习学习!
作者: chensc    时间: 2013-9-27 08:39
学习学习!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2