Java實(shí)現(xiàn)真假隨機(jī)數(shù)詳解
偽隨機(jī)數(shù)
定義:偽隨機(jī)數(shù)(Pseudorandom Number)是通過算法生成的數(shù),其看似隨機(jī),但實(shí)際上是確定性的。
生成方式:通常使用數(shù)學(xué)公式或算法,如線性同余法,基于一個(gè)初始值(種子)產(chǎn)生一個(gè)序列。
特點(diǎn):
- 可再現(xiàn)性:給定相同的種子,偽隨機(jī)數(shù)生成器總是會(huì)產(chǎn)生相同的數(shù)字序列。這對(duì)于測(cè)試和調(diào)試非常有用。
- 效率高:生成速度快,適用于需要大量隨機(jī)數(shù)的場(chǎng)景。
- 周期性:序列是有限長(zhǎng)的,最終會(huì)重復(fù)。
應(yīng)用場(chǎng)景:適用于模擬、數(shù)值分析、游戲開發(fā)等不要求絕對(duì)隨機(jī)性的領(lǐng)域。
真隨機(jī)數(shù)
定義:真隨機(jī)數(shù)(True Random Number)依賴于不可預(yù)測(cè)的物理現(xiàn)象,如放射性衰變、熱噪聲等。
生成方式:通常通過硬件設(shè)備采集自然界中不可預(yù)測(cè)的事件。
特點(diǎn):
- 不可再現(xiàn)性:相同條件下無法生成相同的數(shù)列。
- 不可預(yù)測(cè)性:沒有可預(yù)測(cè)的模式,真正隨機(jī)。
- 復(fù)雜度高:生成過程可能較慢,且需要專門的硬件支持。
應(yīng)用場(chǎng)景:用于安全性要求極高的領(lǐng)域,如密碼學(xué)、加密密鑰生成等。
java偽隨機(jī)數(shù)
java中的Random
類是用于生成偽隨機(jī)數(shù)的工具。其底層實(shí)現(xiàn)依賴于一個(gè)稱為**線性同余生成器(Linear Congruential Generator, LCG)**的算法,這是一種常用的偽隨機(jī)數(shù)生成算法。
線性同余生成器 (LCG)
LCG 是一種通過以下公式生成隨機(jī)序列的算法:
[ X_{n+1} = (a \times X_n + c) \mod m ]
其中:
( X ) 是隨機(jī)數(shù)序列。
( a ), ( c ), 和 ( m ) 是常量:
- ( m ) 是模量,通常是大的質(zhì)數(shù)或2的冪。
- ( a ) 是乘數(shù)。
- ( c ) 是增量。
( X_0 ) 是初始種子值。
Java Random 類的實(shí)現(xiàn)
在Java中,java.util.Random
類使用64位的LGC算法,其中:
- 模量 ( m = 2^{48} )
- 常量 ( a = 25214903917 )
- 增量 ( c = 11 )
每次生成一個(gè)新的隨機(jī)數(shù)時(shí),Random
類會(huì)更新當(dāng)前種子以生成下一個(gè)數(shù)。
種子(Seed)
- 初始化:如果不指定種子,
Random
會(huì)使用系統(tǒng)時(shí)間作為默認(rèn)種子。 - 再現(xiàn)性:相同的種子會(huì)產(chǎn)生相同的隨機(jī)數(shù)序列,這對(duì)測(cè)試和調(diào)試非常有用。
內(nèi)部方法
Java Random
類的核心方法是next(int bits)
,用于生成給定數(shù)量的隨機(jī)bit。其他如nextInt()
, nextDouble()
等方法都基于next(bits)
來實(shí)現(xiàn),只是通過不同的方式組合這些bit。
protected int next(int bits) { long oldseed, nextseed; AtomicLong seed = this.seed; do { oldseed = seed.get(); nextseed = (oldseed * 25214903917L + 11) & ((1L << 48) - 1); } while (!seed.compareAndSet(oldseed, nextseed)); return (int)(nextseed >>> (48 - bits)); }
代碼解釋
1.變量聲明:
oldseed
: 當(dāng)前種子值。nextseed
: 用于計(jì)算下一個(gè)種子值。seed
: 一個(gè)AtomicLong
類型,用于保證線程安全地更新種子。
2.獲取當(dāng)前種子值:
oldseed = seed.get();
: 從原子變量seed
中讀取當(dāng)前的種子值。
3.計(jì)算下一個(gè)種子值:
nextseed = (oldseed * multiplier + addend) & mask;
使用線性同余生成器(LCG)公式來計(jì)算新的種子值。
multiplier
、addend
和mask
是常量,其中:
multiplier
是乘數(shù)。addend
是增量。mask
用于確保結(jié)果在有效范圍內(nèi)(通常是m-1
,其中m
是模量)。
4.更新種子值:
while (!seed.compareAndSet(oldseed, nextseed));
- 使用
compareAndSet
方法嘗試將oldseed
更新為nextseed
。 - 如果在此期間其他線程修改了
seed
,則compareAndSet
會(huì)返回false
,循環(huán)繼續(xù),直到成功為止。這種機(jī)制確保了多線程環(huán)境下的原子性更新。
5.生成隨機(jī)數(shù):
return (int)(nextseed >>> (48 - bits));
- 將新的種子值右移以獲取所需的隨機(jī)位數(shù)。
>>>
操作符確保左側(cè)用零填充,無符號(hào)右移。(48 - bits)
確定要保留多少位的隨機(jī)數(shù)。
總結(jié)
這個(gè)方法利用種子值和線性同余生成器算法來生成偽隨機(jī)數(shù),并通過AtomicLong
保證了多線程情況下的線程安全。它返回的是指定位數(shù)的整數(shù)形式的隨機(jī)數(shù),將會(huì)被其他方法如nextInt()
或nextDouble()
進(jìn)一步處理,以提供給用戶所需的隨機(jī)數(shù)類型。
java真隨機(jī)數(shù)
在Java中,實(shí)現(xiàn)真隨機(jī)數(shù)通常需要依賴外部硬件設(shè)備或者操作系統(tǒng)的功能,因?yàn)榧冘浖椒ㄉ傻亩际莻坞S機(jī)數(shù)。
使用java.security.SecureRandom
雖然SecureRandom
類本質(zhì)上仍然是偽隨機(jī)的,但它可以配置為使用底層操作系統(tǒng)提供的熵源,這樣生成的隨機(jī)數(shù)接近于真隨機(jī)數(shù),特別是在安全性要求較高的應(yīng)用場(chǎng)景中。
import java.security.SecureRandom; public class TrueRandomExample { public static void main(String[] args) { SecureRandom secureRandom = new SecureRandom(); // 生成一個(gè)隨機(jī)整數(shù) int randomInt = secureRandom.nextInt(); System.out.println("Random Integer: " + randomInt); // 生成一個(gè)0到100之間的隨機(jī)整數(shù) int boundedInt = secureRandom.nextInt(101); System.out.println("Bounded Random Integer (0-100): " + boundedInt); // 生成隨機(jī)字節(jié)數(shù)組 byte[] randomBytes = new byte[16]; secureRandom.nextBytes(randomBytes); System.out.println("Random Bytes: " + java.util.Arrays.toString(randomBytes)); } }
SecureRandom 的特點(diǎn)
- 更多的熵來源:
SecureRandom
可以利用操作系統(tǒng)的熵池(如Linux的/dev/random
或/dev/urandom
),這些熵源采集的是物理世界中的不確定性。 - 適用于安全應(yīng)用:廣泛用于加密、令牌生成等需要高質(zhì)量隨機(jī)數(shù)的場(chǎng)合。
- 可配置性:允許指定算法和提供者,以滿足不同的安全需求。
真隨機(jī)數(shù)的硬件支持
如果需要真正的隨機(jī)數(shù),可以使用硬件隨機(jī)數(shù)生成器(HRNG),通常通過專用的硬件設(shè)備來實(shí)現(xiàn),如:
- Intel的RDRAND指令集:在支持的處理器上,這些指令可以直接提供硬件級(jí)別的隨機(jī)數(shù)。
- 其他硬件設(shè)備:市面上有專門的USB接口的隨機(jī)數(shù)生成器,它們通過例如熱噪聲等物理現(xiàn)象生成隨機(jī)數(shù)。
在Java中,直接調(diào)用這些硬件設(shè)備需要通過JNI(Java Native Interface)或者底層的操作系統(tǒng)API,這涉及到特定平臺(tái)的調(diào)用和配置。對(duì)于大多數(shù)應(yīng)用來說,SecureRandom
已經(jīng)能夠提供足夠好的隨機(jī)數(shù)質(zhì)量。
擴(kuò)展:熱噪聲隨機(jī)數(shù)如何理解
熱噪聲隨機(jī)數(shù)是基于物理現(xiàn)象生成的隨機(jī)數(shù),其主要原理是利用電子設(shè)備中的熱噪聲。熱噪聲,又稱為約翰遜-奈奎斯特噪聲,是由于導(dǎo)體中自由電子的熱運(yùn)動(dòng)引起的電壓和電流波動(dòng)。這種波動(dòng)在微觀上是不可預(yù)測(cè)的,因此可以用作隨機(jī)數(shù)的來源。
理解熱噪聲隨機(jī)數(shù)的關(guān)鍵點(diǎn)
物理基礎(chǔ):
- 熱噪聲是由導(dǎo)體內(nèi)電子的隨機(jī)熱運(yùn)動(dòng)產(chǎn)生的,與溫度有關(guān)。
- 這種噪聲存在于所有有電阻的導(dǎo)體中,并且無法完全消除。
生成過程:
- 將熱噪聲信號(hào)通過放大器進(jìn)行放大,以便測(cè)量。
- 使用模數(shù)轉(zhuǎn)換器(ADC)將模擬信號(hào)轉(zhuǎn)換為數(shù)字信號(hào),從而得到隨機(jī)二進(jìn)制數(shù)。
優(yōu)點(diǎn):
- 真正的隨機(jī)性:因?yàn)闊嵩肼暿怯闪孔恿W(xué)效應(yīng)導(dǎo)致的,理論上是不可預(yù)測(cè)的,這使得它非常適合用于安全相關(guān)應(yīng)用,如加密密鑰生成。
- 不重復(fù)性:每個(gè)樣本都是獨(dú)立的,不依賴于之前的任意值或狀態(tài)。
應(yīng)用場(chǎng)景:
用于硬件隨機(jī)數(shù)生成器(HRNG),這些設(shè)備廣泛應(yīng)用于需要高安全性和高質(zhì)量隨機(jī)數(shù)的領(lǐng)域,如密碼學(xué)、安全通信等。
實(shí)現(xiàn)難點(diǎn):
- 需要專門的硬件支持,比如隨機(jī)數(shù)生成芯片或設(shè)備。
- 噪聲的放大和測(cè)量需要精確的電路設(shè)計(jì),以確保環(huán)境噪聲不會(huì)干擾結(jié)果。
通過理解熱噪聲及其應(yīng)用,我們可以更好地選擇適合各種需求的隨機(jī)數(shù)生成器。對(duì)于一般的軟件應(yīng)用,偽隨機(jī)數(shù)生成已經(jīng)足夠,而在高度安全的場(chǎng)合,硬件級(jí)別的真隨機(jī)數(shù)生成是必需的。
到此這篇關(guān)于Java實(shí)現(xiàn)真假隨機(jī)數(shù)詳解的文章就介紹到這了,更多相關(guān)Java真假隨機(jī)數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java通過snmp協(xié)議獲取物理設(shè)備信息
這篇文章主要介紹了java通過snmp協(xié)議獲取物理設(shè)備信息,snmp中文含義是簡(jiǎn)單網(wǎng)絡(luò)管理協(xié)議,可用完成對(duì)計(jì)算機(jī)、路由器和其他網(wǎng)絡(luò)設(shè)備的遠(yuǎn)程管理和監(jiān)視,本文我們是通過java程序來獲取,需要的朋友可以參考下2023-07-07Spring細(xì)數(shù)兩種代理模式之靜態(tài)代理和動(dòng)態(tài)代理概念及使用
代理是一種設(shè)計(jì)模式,提供了對(duì)目標(biāo)對(duì)象另外的訪問方式,即通過代理對(duì)象訪問目標(biāo)對(duì)象??梢圆恍薷哪繕?biāo)對(duì)象,對(duì)目標(biāo)對(duì)象功能進(jìn)行拓展。在我們學(xué)習(xí)Spring的時(shí)候就會(huì)發(fā)現(xiàn),AOP(面向切面編程)的底層就是代理2023-02-02一文詳解Redisson分布式鎖底層實(shí)現(xiàn)原理
這篇文章主要詳細(xì)介紹了Redisson分布式鎖底層實(shí)現(xiàn)原理,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07java?-jar命令及SpringBoot通過java?-jav啟動(dòng)項(xiàng)目的過程
本篇文章將為大家講述關(guān)于 SpringBoot 項(xiàng)目工程完成后,是如何通過 java-jar 命令來啟動(dòng)的,以及介紹 java-jar 命令的詳細(xì)內(nèi)容,對(duì)SpringBoot java?-jav啟動(dòng)過程感興趣的朋友跟隨小編一起看看吧2023-05-05