从随机字节生成随机浮点数而无需位旋转
Generate random floats from random bytes without bit-twiddling
假设我有足够好的 (tm) 随机字节值流,是否有一种数学方法可以将它们转换为 (0 < n < 1) 不需要知道内部格式的浮点值的花车?
我正在寻找这样的东西:
- 不需要按位运算(在浮点数上),并且
- 是一个迭代过程,我们可以知道在n次迭代后会给出一个好的值,其中n是输出精度的函数。
- 可用于任何精度浮点数的通用过程,只需更改迭代次数,即消耗更多输入字节来生成双精度浮点数而不是单精度浮点数。
天真的解决方案是只用几个字节为自己构建一个大整数,然后简单地转换为除以 2^n 的浮点数,但我看不出如何在不弄乱分布的情况下做到这一点。
另一个想法是这样的(伪代码):
state := 0.0
n := requiredIterations(outputPrecision)
for(1..n)
nextByte := getRandomByte()
state := state + nextByte
state := state / 256
end
return state
看起来这应该可行,但我不知道如何证明它:)
正如 Severin Pappadeux 所说,为什么不做类似的事情
const double factor = 2.32830643653869628906e-10; // 2^(-32)
unsigned int accumulator = 0;
for (int i = 0; i != 4; ++i)
{
accumulator <<= 8;
accumulator |= getRandomByte();
}
double r = factor * accumulator;
好的,我想我有你需要的东西
让我们考虑按以下方式在 [0...1) 范围内对浮点数进行采样。 256 是 2^8,相当于下一个字节移位。让我们将字节合并为
b0*256*256*256 + b1*256*256 + b2*256 + b3
要获得 [0...1) 范围内的数字,您必须将其除以 256*256*256*256,因此
f = b0/256 + b1/(256*256) + b2/(256*256*256) + b3/(256*256*256*256)
这又等同于多项式计算的 Horner 方案
f = (1/256)*(b0 + (1/256)*(b1 + (1/256)*(b2 + (1/256)*b3)))
反过来,这几乎是你写的(对于一些抽象的 N)
假设我有足够好的 (tm) 随机字节值流,是否有一种数学方法可以将它们转换为 (0 < n < 1) 不需要知道内部格式的浮点值的花车?
我正在寻找这样的东西:
- 不需要按位运算(在浮点数上),并且
- 是一个迭代过程,我们可以知道在n次迭代后会给出一个好的值,其中n是输出精度的函数。
- 可用于任何精度浮点数的通用过程,只需更改迭代次数,即消耗更多输入字节来生成双精度浮点数而不是单精度浮点数。
天真的解决方案是只用几个字节为自己构建一个大整数,然后简单地转换为除以 2^n 的浮点数,但我看不出如何在不弄乱分布的情况下做到这一点。
另一个想法是这样的(伪代码):
state := 0.0
n := requiredIterations(outputPrecision)
for(1..n)
nextByte := getRandomByte()
state := state + nextByte
state := state / 256
end
return state
看起来这应该可行,但我不知道如何证明它:)
正如 Severin Pappadeux 所说,为什么不做类似的事情
const double factor = 2.32830643653869628906e-10; // 2^(-32)
unsigned int accumulator = 0;
for (int i = 0; i != 4; ++i)
{
accumulator <<= 8;
accumulator |= getRandomByte();
}
double r = factor * accumulator;
好的,我想我有你需要的东西
让我们考虑按以下方式在 [0...1) 范围内对浮点数进行采样。 256 是 2^8,相当于下一个字节移位。让我们将字节合并为
b0*256*256*256 + b1*256*256 + b2*256 + b3
要获得 [0...1) 范围内的数字,您必须将其除以 256*256*256*256,因此
f = b0/256 + b1/(256*256) + b2/(256*256*256) + b3/(256*256*256*256)
这又等同于多项式计算的 Horner 方案
f = (1/256)*(b0 + (1/256)*(b1 + (1/256)*(b2 + (1/256)*b3)))
反过来,这几乎是你写的(对于一些抽象的 N)