程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java中隨機數的發生方式與原理詳解

Java中隨機數的發生方式與原理詳解

編輯:關於JAVA

Java中隨機數的發生方式與原理詳解。本站提示廣大學習愛好者:(Java中隨機數的發生方式與原理詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是Java中隨機數的發生方式與原理詳解正文


Java中隨機數的發生方式與原理

查閱隨機數相關材料,特做整理

首先說一下java中發生隨機數的幾種方式

    在j2se中我們可以運用Math.random()辦法來發生一個隨機數,這個發生的隨機數是0-1之間的一個double,我們可以把他乘以100,他就是個100以內的隨機數字,這個在j2me中沒有。 在java.util這個包外面提供了一個Random的類,我們可以新建一個Random的對象來發生隨機數,他可以消費隨機整數、隨機float、隨機double、隨機long,這個也是我們在j2me的順序裡常常用的一個取隨機數的辦法。 在我們的System類中有一個currentTimeMillis()辦法,這個辦法前往一個從1970年1月1號0點0分0秒到目前的一個毫秒數,前往類型是long,我們可以拿他作為一個隨機數,我們可以拿他對一些數取模,就可以把他限制在一個范圍之內啦。

EN。。。其真實Random的默許結構辦法裡也是運用下面第三種辦法停止隨機數的發生的。

關於辦法二中的Random類有兩種構建方式:帶種子和不帶種子

不帶種子:此種方式將會前往隨機的數字,每次運轉後果不一樣,相當於用System.currentTimeMillis()作種子。

帶種子:此種方式,無論順序運轉多少次,前往後果都是一樣的。假如用相反的種子創立兩個Random實例,則對每個實例停止相反的辦法調用序列,它們將生成並前往相反的數字序列。

偽隨機數

計算機中的隨機數都是偽隨機數

上面看這樣一個C順序:

// rand_1.cpp
#include <stdlib.h>
static unsigned int RAND_SEED;
unsigned int random(void)
{
  RAND_SEED = (RAND_SEED*123+59)%65536;
  return (RAND_SEED);
}
void random_start(void)
{
  int temp[2];
  movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);
  RAND_SEED = temp[0];
}
void main()
{
  unsigned int i,n;
  random_start();
  for(i=0;i<10;i++)
     printf("#u\t",random());
  printf("\n");
}

它完好地論述了隨機數發生的進程:

首先,

movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);

這個函數用來挪動內存數據,其中FP_SEG(far pointer to segment)是取temp數組段地址的函數,FP_OFF(far pointer to offset)是取temp數組絕對地址的函數,movedata函數的作用是把位於0040:006CH存儲單元中的雙字放到數組temp的聲明的兩個存儲單元中。這樣可以經過temp數組把0040:006CH處的一個16位的數送給RAND_SEED。
其次,

RAND_SEED=(RAND_SEED*123+59)%65536;

是用來計算隨機數的辦法,隨機數的計算辦法在不同的計算機中是不同的,即便在相反的計算機中裝置的不同的操作零碎中也是不同的。我在linux和windows下辨別試過,相反的隨機種子在這兩種操作零碎中生成的隨機數是不同的,這闡明它們的計算辦法不同。

然後,

movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);

隨機種子為什麼要在內存的0040:006CH處取?0040:006CH處寄存的是什麼?

學過《計算機組成原理與接口技術》這門課的人能夠會記得在編制ROM BIOS時鐘中綴服務順序時會用到Intel 8253定時/計數器,它與Intel 8259中綴芯片的通訊使得中綴服務順序得以運轉,主板每秒發生的18.2次中綴正是處置器依據定時/記數器值控制中綴芯片發生的。在我們計算機的主機板上都會有這樣一個定時/記數器用來計算以後零碎時間,每過一個時鐘信號周期都會使記數器加一,而這個記數器的值寄存在哪兒呢?沒錯,就在內存的0040:006CH處,其實這一段內存空間是這樣定義的:

TIMER_LOW DW ? ;地址為 0040:006CH
TIMER_HIGH DW ? ;地址為 0040:006EH
TIMER_OFT DB ? ;地址為 0040:0070H

時鐘中綴服務順序中,每當TIMER_LOW轉滿時,此時,記數器也會轉滿,記數器的值歸零,即TIMER_LOW處的16位二進制歸零,而TIMER_HIGH加一。rand01.c中的

movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);

正是把TIMER_LOW和TIMER_HIGH兩個16位二進制數放進temp數組,再送往RAND_SEED,從而取得了“隨機種子”。
如今,可以確定的一點是,隨機種子來自零碎時鐘,確切地說,是來自計算機主板上的定時/計數器在內存中的記數值。

EN...沒有最後。。lvl--

再看一段代碼:

//rand_2.cpp
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
  srand((unsigned)time(NULL));
  unsigned int r=rand();
  cout<<"r = "<<r<<endl; //依據C++ 98規范,可以不必return語句來引見main函數
  return 0;
}

這裡用戶和其他順序沒有設定隨機種子,則運用零碎定時/計數器的值做為隨機種子,所以,在相反的平台環境下,編譯生成exe後,每次運轉它,顯示的隨機數會是偽隨機數,即每次運轉顯示的後果會有不同。

總結

隨機數是由隨機種子依據一定的計算辦法計算出來的數值。所以,只需計算辦法一定,隨機種子一定,那麼發生的隨機數就不會變。在相反的平台環境下,編譯生成exe後,每次運轉它,顯示的隨機數都是一樣的。這是由於在相反的編譯平台環境下,由隨機種子生成隨機數的計算辦法都是一樣的,再加上隨機種子一樣,所以發生的隨機數就是一樣的。

只需用戶或第三方不設置隨機種子,那麼在默許狀況下隨機種子來自零碎時鐘(即定時/計數器的值)

感激閱讀,希望能協助到大家,謝謝大家對本站的支持!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved