不要隨便設置隨機種子


  隨機數在太多的地方使用了,比如加密、混淆數據等,我們使用隨機數是期望獲得一個唯一的、不可仿造的數字,以避免產生相同的業務數據造成混亂。在Java項目中通常是通過Math.random方法和Random類來獲得隨機數的,我們來看一段代碼:

  1. public class Client {  
  2.      public static void main(String[] args) {  
  3.           Random r = new Random();  
  4.           for(int i=1;i<4;i++){  
  5.             System.out.println("第"+i+"次:"+r.nextInt());  
  6.         }  
  7.      }  

 

代碼很簡單,我們一般都是這樣獲得隨機數的,運行此程序可知:三次打印的隨機數都不相同,即使多次運行結果也不同,這也正是我們想要隨機數的原因。我們再來看下面的程序:

  1. public class Client {  
  2.      public static void main(String[] args) {  
  3.           Random r = new Random(1000);  
  4.           for(int i=1;i<4;i++){  
  5.             System.out.println("第"+i+"次:"+r.nextInt());  
  6.           }  
  7.      }  

 

上面使用了Random的有參構造,運行結果如下:

 

  1. 第1次:-498702880  
  2. 第2次:-858606152  
  3. 第3次:1942818232 

計算機不同輸出的隨機數也不同,但是有一點是相同的:在同一台機器上,甭管運行多少次,所打印的隨機數都是相同的,也就是說第一次運行,會打印出這三個隨機數,第二次運行還是打印出這三個隨機數,只要是在同一台硬件機器上,就永遠都會打印出相同的隨機數,似乎隨機數不隨機了,問題何在?

那是因為產生隨機數的種子被固定了,在Java中,隨機數的產生取決於種子,隨機數和種子之間的關系遵從以下兩個規則:

種子不同,產生不同的隨機數。

種子相同,即使實例不同也產生相同的隨機數。

看完上面兩個規則,我們再來看這個例子,會發現問題就出在有參構造上,Random類的默認種子(無參構造)是System.nanoTime()的返回值(JDK 1.5版本以前默認種子是System. currentTimeMillis()的返回值),注意這個值是距離某一個固定時間點的納秒數,不同的操作系統和硬件有不同的固定時間點,也就是說不同的操作系統其納秒值是不同的,而同一個操作系統納秒值也會不同,隨機數自然也就不同了。(順便說下,System.nanoTime不能用於計算日期,那是因為“固定”的時間點是不確定的,納秒值甚至可能是負值,這點與System. currentTimeMillis不同。)

new Random(1000)顯式地設置了隨機種子為1000,運行多次,雖然實例不同,但都會獲得相同的三個隨機數。所以,除非必要,否則不要設置隨機種子。

順便提一下,在Java中有兩種方法可以獲得不同的隨機數:通過java.util.Random類獲得隨機數的原理和Math.random方法相同,Math.random()方法也是通過生成一個Random類的實例,然后委托nextDouble()方法的,兩者是殊途同歸,沒有差別。

注意 若非必要,不要設置隨機數種子。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM