Java中隨機數(shù)的產(chǎn)生方式與原理詳解
Java中隨機數(shù)的產(chǎn)生方式與原理
查閱隨機數(shù)相關(guān)資料,特做整理
首先說一下java中產(chǎn)生隨機數(shù)的幾種方式
- 在j2se中我們可以使用Math.random()方法來產(chǎn)生一個隨機數(shù),這個產(chǎn)生的隨機數(shù)是0-1之間的一個double,我們可以把他乘以100,他就是個100以內(nèi)的隨機數(shù)字,這個在j2me中沒有。
- 在java.util這個包里面提供了一個Random的類,我們可以新建一個Random的對象來產(chǎn)生隨機數(shù),他可以生產(chǎn)隨機整數(shù)、隨機float、隨機double、隨機long,這個也是我們在j2me的程序里經(jīng)常用的一個取隨機數(shù)的方法。
- 在我們的System類中有一個currentTimeMillis()方法,這個方法返回一個從1970年1月1號0點0分0秒到目前的一個毫秒數(shù),返回類型是long,我們可以拿他作為一個隨機數(shù),我們可以拿他對一些數(shù)取模,就可以把他限制在一個范圍之內(nèi)啦。
EN。。。其實在Random的默認(rèn)構(gòu)造方法里也是使用上面第三種方法進(jìn)行隨機數(shù)的產(chǎn)生的。
對于方法二中的Random類有兩種構(gòu)建方式:帶種子和不帶種子
不帶種子:此種方式將會返回隨機的數(shù)字,每次運行結(jié)果不一樣,相當(dāng)于用System.currentTimeMillis()作種子。
帶種子:此種方式,無論程序運行多少次,返回結(jié)果都是一樣的。如果用相同的種子創(chuàng)建兩個Random實例,則對每個實例進(jìn)行相同的方法調(diào)用序列,它們將生成并返回相同的數(shù)字序列。
偽隨機數(shù)
計算機中的隨機數(shù)都是偽隨機數(shù)
下面看這樣一個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"); }
它完整地闡述了隨機數(shù)產(chǎn)生的過程:
首先,
movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);
這個函數(shù)用來移動內(nèi)存數(shù)據(jù),其中FP_SEG(far pointer to segment)是取temp數(shù)組段地址的函數(shù),F(xiàn)P_OFF(far pointer to offset)是取temp數(shù)組相對地址的函數(shù),movedata函數(shù)的作用是把位于0040:006CH存儲單元中的雙字放到數(shù)組temp的聲明的兩個存儲單元中。這樣可以通過temp數(shù)組把0040:006CH處的一個16位的數(shù)送給RAND_SEED。
其次,
RAND_SEED=(RAND_SEED*123+59)%65536;
是用來計算隨機數(shù)的方法,隨機數(shù)的計算方法在不同的計算機中是不同的,即使在相同的計算機中安裝的不同的操作系統(tǒng)中也是不同的。我在linux和windows下分別試過,相同的隨機種子在這兩種操作系統(tǒng)中生成的隨機數(shù)是不同的,這說明它們的計算方法不同。
然后,
movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);
隨機種子為什么要在內(nèi)存的0040:006CH處???0040:006CH處存放的是什么?
學(xué)過《計算機組成原理與接口技術(shù)》這門課的人可能會記得在編制ROM BIOS時鐘中斷服務(wù)程序時會用到Intel 8253定時/計數(shù)器,它與Intel 8259中斷芯片的通信使得中斷服務(wù)程序得以運轉(zhuǎn),主板每秒產(chǎn)生的18.2次中斷正是處理器根據(jù)定時/記數(shù)器值控制中斷芯片產(chǎn)生的。在我們計算機的主機板上都會有這樣一個定時/記數(shù)器用來計算當(dāng)前系統(tǒng)時間,每過一個時鐘信號周期都會使記數(shù)器加一,而這個記數(shù)器的值存放在哪兒呢?沒錯,就在內(nèi)存的0040:006CH處,其實這一段內(nèi)存空間是這樣定義的:
TIMER_LOW DW ? ;地址為 0040:006CH
TIMER_HIGH DW ? ;地址為 0040:006EH
TIMER_OFT DB ? ;地址為 0040:0070H
時鐘中斷服務(wù)程序中,每當(dāng)TIMER_LOW轉(zhuǎn)滿時,此時,記數(shù)器也會轉(zhuǎn)滿,記數(shù)器的值歸零,即TIMER_LOW處的16位二進(jìn)制歸零,而TIMER_HIGH加一。rand01.c中的
movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);
正是把TIMER_LOW和TIMER_HIGH兩個16位二進(jìn)制數(shù)放進(jìn)temp數(shù)組,再送往RAND_SEED,從而獲得了“隨機種子”。
現(xiàn)在,可以確定的一點是,隨機種子來自系統(tǒng)時鐘,確切地說,是來自計算機主板上的定時/計數(shù)器在內(nèi)存中的記數(shù)值。
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; //根據(jù)C++ 98標(biāo)準(zhǔn),可以不用return語句來介紹main函數(shù) return 0; }
這里用戶和其他程序沒有設(shè)定隨機種子,則使用系統(tǒng)定時/計數(shù)器的值做為隨機種子,所以,在相同的平臺環(huán)境下,編譯生成exe后,每次運行它,顯示的隨機數(shù)會是偽隨機數(shù),即每次運行顯示的結(jié)果會有不同。
總結(jié)
隨機數(shù)是由隨機種子根據(jù)一定的計算方法計算出來的數(shù)值。所以,只要計算方法一定,隨機種子一定,那么產(chǎn)生的隨機數(shù)就不會變。在相同的平臺環(huán)境下,編譯生成exe后,每次運行它,顯示的隨機數(shù)都是一樣的。這是因為在相同的編譯平臺環(huán)境下,由隨機種子生成隨機數(shù)的計算方法都是一樣的,再加上隨機種子一樣,所以產(chǎn)生的隨機數(shù)就是一樣的。
只要用戶或第三方不設(shè)置隨機種子,那么在默認(rèn)情況下隨機種子來自系統(tǒng)時鐘(即定時/計數(shù)器的值)
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
- 如何用java生成指定范圍的隨機數(shù)
- 史上最全的java隨機數(shù)生成算法分享
- Java實現(xiàn)按權(quán)重隨機數(shù)
- JAVA獲得包含0-9、a-z、A-Z范圍內(nèi)字符串的的隨機數(shù)實例
- java生成隨機數(shù)(字符串)示例分享
- Java生成10個1000以內(nèi)的隨機數(shù)并用消息框顯示數(shù)組內(nèi)容然后求和輸出
- Java編程中隨機數(shù)的生成方式總結(jié)
- Java中生成隨機數(shù)的實現(xiàn)方法總結(jié)
- java生成抽樣隨機數(shù)的多種算法
- java 實現(xiàn)隨機數(shù)組輸出及求和實例詳解
- java生成隨機數(shù)的方法
- java生成隨機數(shù)的常用方法分析
相關(guān)文章
解讀Java和JavaScript區(qū)別與聯(lián)系
這篇文章主要介紹了解讀Java和JavaScript區(qū)別與聯(lián)系,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02Java整數(shù)和字符串相互轉(zhuǎn)化實例詳解
這篇文章主要介紹了Java整數(shù)和字符串相互轉(zhuǎn)化實例詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-02-02Java實現(xiàn)List去重的幾種方法總結(jié)
這篇文章主要為大家詳細(xì)介紹了Java中List去重的幾種常用方法總結(jié),文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)和參考價值,需要的小伙伴可以了解一下2023-09-09SpringSecurity自定義資源攔截規(guī)則及登錄界面跳轉(zhuǎn)問題
這篇文章主要介紹了SpringSecurity自定義資源攔截規(guī)則及登錄界面跳轉(zhuǎn)問題,我們想要自定義認(rèn)證邏輯,就需要創(chuàng)建一些原來不存在的bean,這個時候就可以使@ConditionalOnMissingBean注解,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-12-12mybatis sum(參數(shù)) 列名作為參數(shù)的問題
這篇文章主要介紹了mybatis sum(參數(shù)) 列名作為參數(shù)的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01Java實戰(zhàn)房屋租賃網(wǎng)的實現(xiàn)流程
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+jsp+mysql+maven實現(xiàn)一個房屋租賃網(wǎng)站,大家可以在過程中查缺補漏,提升水平2021-11-11