从随机字节生成随机浮点数而不会产生比特错误

时间:2015-02-05 23:21:42

标签: random floating-point

假设我有一个足够好的(tm)随机字节值流,是否有一种数学方法将这些转换为(0

我正在寻找的东西:

  • 不需要按位操作(在浮点数上)和
  • 我们可以知道的迭代过程在n次迭代后会给出一个好的值,其中n是输出精度的函数。
  • 一个可用于任何精度浮点数的通用过程,只需更改迭代次数,即消耗更多输入字节以生成双精度浮点数。

天真的解决方案是从几个字节构建一个大整数,然后简单地转换为浮动除以2 ^ n,但我不知道怎么做而不会搞乱分发。

另一个想法是这样的(伪代码):

state := 0.0
n := requiredIterations(outputPrecision)
for(1..n)
    nextByte := getRandomByte()
    state := state + nextByte
    state := state / 256
end
return state

看起来这应该有效,但我不知道如何证明:)

2 个答案:

答案 0 :(得分:3)

好吧,我想我已经得到了你需要的东西

让我们考虑以下列方式在[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)

答案 1 :(得分:-1)

正如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;