随机:计算机是这么计算的

计算机是怎么生成随机数的?不会编程你也能看得懂。

随机:计算机是这么计算的

最早的现代计算机


中间平方法Middle-square method

世界上第一台计算机是1945年制造的ENIAC。现代计算机之父冯诺依曼John Von Neumann在它的基础上改进成为真正意义上的现代计算机。

而在这个时候,计算机刚刚起步的时候,冯诺依曼就说了这么一句话,如果谁想用数学方法生成随机数字,那么他一定是落入了原罪。

“Any one who considers arithmetical methods of producing random digits is, of course, in a state of sin.”
——John Von Neumann.

冯诺依曼是博弈论的创始人,在量子力学方面也很有成就,在他开启计算机时代之初,就指明了真随机不可能依靠数学和计算机方法实现。

但为了计算机的制造,冯诺依曼发明了一个很粗糙的伪随机PRNG方法:中间平方法。

随机:计算机是这么计算的

给定一个六位数作为种子,比如675248,那么先把它平方,比如得到455959861504,然后再掐头去尾取中间6个数字,把它当做随机数结果,如图中的959861。当然这个计算流程可以继续重复下去,就能得到一些列随机六位数。

Python代码如下:

seed_number = int(input("请输入一个六位数:"))
number = seed_number
already_seen = set()
counter = 0

while number not in already_seen:
counter += 1
already_seen.add(number)
number = int(str(number * number).zfill(12)[3:9])
print(f"#{counter}: {number}")

print(f"开始于{seed_number}, 共{counter}步之后出现重复数字{number}.")

对于6位数来说,一般在数百次之后就会发生重复循环。这随机方法真的很粗糙。

威尔的PRNG

20世纪30年代兴起的普林斯顿高等研究院IAS可以说是自然科学的圣地,爱因斯坦、计算机理论先驱哥德尔、原子弹之父奥本海默、现代计算机之父冯诺依曼,日本数学家小平邦彦和华裔物理学家杨振宁、李政道都曾在此学习或工作。

冯诺依曼是个犹太人,原本居住匈牙利,然而由于希特勒的统治影响,他来到了美国。而把他介绍到普林斯顿的正是另一位伟大的科学家赫尔曼·威尔Hermann Weyl。

威尔这次又改进了冯诺依曼的中间平方随机程序。

这是一段C++代码:

#include <stdint.h>
#include <stdio.h>

uint64_t x = 0, w = 0, s = 0xb5ad4eceda1ce2a9;

inline static uint32_t msws() {

x *= x;
x += (w += s);
return x = (x>>32) | (x<<32);

}
int main(){
for(int i=0;i<10;i++){
printf("%d\\n",msws());
}
}
/<stdio.h>/<stdint.h>

双箭头在这里是移位操作,<>则是除以2的32次方。
这里的思路是每次都把种子x平方,并且加上一个w,而且w每次都增大s,这里s是个很大十六进制数字,它足以超过2的32次方。

注意x,w,s都是uint64,是64位的,而msws()返回的是uint32位数字,实际上这相当于对大数字进行截取成为小数字,本质是和冯诺依曼截取平方数字的中间部分是一个道理。

用0x开头表示是16进制,即不是0到9之后进1位,而是0...9abcdef再进一位,共0到f十六个数字。

运行后会输出一串随机的数字。

随机:计算机是这么计算的

看上去还不错,这个可能是目前最快的伪随机程序算法,因为它只有加法、乘法和移位操作。


分享到:


相關文章: