Lam*_*Psi 6 random floating-point cross-platform r
在 R 4.1.1 中运行以下代码会在平台之间产生不同的结果。
set.seed(1)
x <- rnorm(3)[3]
print(x, 22)
# -0.83562861241004716 # intel windows
# -0.8356286124100471557341 # m1 mac
print(round(x, 15), 22)
# -0.83562861241004704 # intel windows
# -0.8356286124100470447118 # m1 mac
Run Code Online (Sandbox Code Playgroud)
我知道差异的大小如下.Machine$double.eps,并且额外的数字不携带有意义的信息。
我对存在额外数字这一事实并不满意。如何确保结果完全一致?有没有一个 RNG 库可以实现这一点?
编辑:
位表示不同。
set.seed(1)
x <- rnorm(100)
x <- sum(x)
SoDA::binaryRep(x)
.10101110001110000100001111110111000010011001011111011 # intel windows
.10101110001110000100001111110111000010011001011111110 # m1 mac
Run Code Online (Sandbox Code Playgroud)
位也不同runif()。这表明均匀到高斯的转换并不是唯一的突破点。
set.seed(1)
x <- runif(10000000)
x <- sum(x)
SoDA::binaryRep(x)
# kind = "Mersenne-Twister"
.10011000100101000110100110111100101000100000101100000 # intel windows
.10011000100101000110100110111100101000011111001100000 # m1 mac
# kind = "Wichmann-Hill"
.10011000100111111110101000100001001001010100000011011 # intel windows
.10011000100111111110101000100001001001010100001001010 # m1 mac
# kind = "Marsaglia-Multicarry"
.10011000100011100110000010000001011100011110100001110 # intel windows
.10011000100011100110000010000001011100011110001010000 # m1 mac
# kind = "Super-Duper"
.10011000100010011010010110100001000101100011101011110 # intel windows
.10011000100010011010010110100001000101100100001111101 # m1 mac
# kind = "Knuth-TAOCP-2002"
.10011000101000110101010111000111010011101001000101100 # intel windows
.10011000101000110101010111000111010011101001000101101 # m1 mac
# kind = "Knuth-TAOCP"
.10011000100110001011010011000001011001001110011111000 # intel windows
.10011000100110001011010011000001011001001110011111001 # m1 mac
# kind = "L'Ecuyer-CMRG"
.10011000100100010110100101101001011000000111010110101 # intel windows
.10011000100100010110100101101001011000001000010100001 # m1 mac
Run Code Online (Sandbox Code Playgroud)
(10 月 29 日和 11 月 2 日的评论移至此处并进行了编辑。)
我应该指出,当涉及浮点运算时,伪随机数生成器 (PRNG) 可能会出现这种微妙的再现性问题。例如,Intel 的指令集架构可能会使用 80 位扩展精度进行内部算术。然而,扩展精度只是浮点运算可能导致不可再现的伪随机数的一种方式(在许多其他方式中)。考虑到 Intel 和 Arm 的指令集架构差异很大,足以导致再现性问题。(如果我理解的话,Arm 指令集就是苹果 M1 芯片中使用的指令集。)
相比之下,整数运算的再现性问题较少。
因此,如果逐位再现性对您很重要,您应该尝试找到一种仅使用整数运算的 R 语言 PRNG。(事实上,计算机通过整数生成伪随机浮点数,而不是相反,并且大多数 PRNG 生成整数,而不是浮点数。)
例如,对于均匀变量,获取 Mersenne Twister 算法的整数输出而不对其进行操作。对于高斯(和指数)随机变量,幸运的是,Karney 有一种算法,只需整数运算即可生成任意精度的变量。另外,请考虑基于基础整数运算构建的有理算术。
参考:
Karney, CFF, 2016。完全从正态分布中采样。ACM 数学软件汇刊 (TOMS),42(1),第 1-14 页。