当前位置: 首页 > 后端技术 > Python

Pure_PRNG-高质量伪随机数生成器的Py库

时间:2023-03-26 13:07:29 Python

这是IBM在1960年代发明的RANDU伪随机数生成算法输出值的3D可视化。以每三个连续的输出值作为一个点坐标,你会清楚地看到这些点在三维空间中只规则分布在15个平面上!结果,那段时间使用这个算法的很多论文的结论都是不可靠的。理想的伪随机数生成点应均匀分布在整个空间中。RANDU算法是一类线性同余生成器(LCG)。LCG的优点是简单快速,数学推导清晰,可以计算出超长周期的全周期参数。然而,缺点是连续值之间存在序列相关性,从而导致固有的点阵结构。用于在n维空间生成点时,参数经过精心选择,点会分布在高维空间的超平面上。如果参数选择不当,就会像RANDU一样聚集在低维空间的平面上。直接使用LCG的输出值是无法通过重复的随机数统计检验的。但是,在输出中加入混淆层,大大提高了输出的统计质量,可以通过一系列的随机数统计检验。这就是著名的伪随机数生成器PCG算法——LCG+混淆的原理。非线性二次同余(QCG)和三次同余(CCG)的优缺点与LCG基本相同。逆同余生成器(ICG)没有明显的格结构,可以直接轻松地通过很高维度的统计检验。非常适合金融市场数据模拟等这些高维应用。请参阅5.4.3逆生成器。但是,ICG也存在同余生成元所具有的长期相关性问题。使生成器的周期比应用程序需要的大得多,并且与长周期相关的缺点不是问题。Python随机库使用的伪随机数生成算法是“MersenneTwister”(MT)。该算法因其超长周期而被广泛使用。但是,MT算法无法通过一些随机数统计测试(TestU01套件)。算法内部扩散差,01不平衡。对于需要独立随机数生成器的蒙特卡洛模拟,通常不适合使用仅种子值不同(而不是其他参数)的多个MT实例。本人测试整理了一个可以通过多种随机数统计测试套件的PRNG算法,如下:算法循环二次同余生成器(QCG)+混淆2^256(默认)三次同余生成器(CCG)+混淆2^256(default)InversiveCongruentialGenerator(ICG)102*2^256PCG64_XSL_RR2^128PCG64_DXSM2^128LCG64_32_ext2^128LCG128Mix_XSL_RR2^128LCG128Mix_DXSM2^128LCG128Mix_MURMUR32^128PhiloxCounter4*2^(4*64)ThreeFryCounter4*2^(4*64)AESCounter2^128ChaChaCounter2^128SPECKCounter2^129XSM642^128EFIIX642^64SplitMix642^64Ran642^64然后实现了包含这些算法的伪随机数生成器的Py库源码并放到了GitHub上,https://github.com/fsssosei/P...已在PyPI上发表,可以很方便的安装和分发:pipinstallpure-prngimportfrompure_prng_packageimportpure_prng很简单,可以用,默认的PRNG算法是CCG>>>seed=170141183460469231731687303715884105727#Theseedvaluetowriteatwill>>>prng_instance=pure_prng(seed)>>>source_random_number=prng_instance.source_random_number()>>>next(source_random_number)65852230656997158461166665751696465914198450243194923777324019418213544382100QCG、CCG和LCG64_32_ext这三种是可变周期算法>>>prng_实例=pure_prng(seed,new_prng_period=2**512)>>>source_random_number=prng_instance.source_random_number()>>>next(source_random_number)8375486648769878807557228126183349922765245383564825377649864304632902242469125910865615742661048315918259479944116325466004411700005484642554244082978452其他PRNG算法是固定周期算法但是,库中有method可设置输出随机数序列的周期(不论哪种PRNG算法生成的随机数)>>>period=115792089237316195423570985008687907853269984665640564039457584007913129639747#随意写的周期>>>prng_instance=pure_prng(seed)>>>rand_with_period=prng_instance.rand_with_period(period)>>>next(rand_with_period)mpz(65852230656997158461166665751696465914198450243194923777324019418213544381986)库中还有method生成任意精度浮点随机数>>>seed=170141183460469231731687303715884105727>>>prng_instance=pure_prng(seed)>>>rand_float=prng_instance.rand_float(100)>>>next(rand_float)mpfr('0.56576176351048513846261940831522',100)

猜你喜欢