在给定二进制随机数生成器的情况下生成随机浮点的正确方法?

orl*_*rlp 9 c++ random uniform

假设我们有一个二进制随机数生成器,int r();它将返回零或一个两者,可用性为0.5.

我查看了Boost.Random,然后他们生成32位并执行类似的操作(伪代码):

x = double(rand_int32());
return min + x / (2^32) * (max - min);
Run Code Online (Sandbox Code Playgroud)

我对此有一些严重的怀疑.双尾有53位尾数,32位永远不能正确生成完全随机的尾数,其中包括舍入误差等.

假设IEEE754 ,创建均匀分布float或double半开放范围的快速方法是[min, max)什么?这里的重点在于分配的正确性,而不是速度.

为了正确定义正确,正确的分布将等于我们如果采用无限精确均匀分布的随机数发生器将得到的正确分布,并且对于每个数字,我们将舍入到最接近的IEEE754表示,如果该表示仍然在[min, max)否则该数字不计入分配.

PS:我也会对开放范围的正确解决方案感兴趣.

Chr*_*ies 2

这里的问题是,在 IEEE754 中,可以表示的双精度数不是均匀分布的。也就是说,如果我们有一个生成实数的生成器,例如 (0,1) 中的实数,然后映射到 IEEE754 可表示的数字,则结果将不是均匀分布的。

因此,我们必须定义“公平分配”。也就是说,假设每个 IEEE754 数字只是位于 IEEE754 舍入定义的区间内的概率的代表,则首先生成均匀分布的“数字”和舍入到 IEEE754 的过程将生成(根据定义)“ IEEE754 号码的“均匀分布”。

因此,我相信,如果我们选择足够高的精度,上面的公式将变得任意接近这样的分布。如果我们将问题限制为在 [0,1) 中查找数字,这意味着限制为非标化 IEEE 754 数字集,这些数字与 53 位整数一对一。因此,由 53 位二进制随机数生成器生成尾数应该是快速且正确的。

IEEE 754 算术始终是“以无限精度进行算术,然后进行舍入”,即表示 a b 的 IEEE754 数字是最接近 a b 的数字(换句话说,您可以认为 a*b 以无限精度计算,然后舍入到关闭 IEEE754 编号)。因此,我相信 min + (max-min) * x(其中 x 是非标化数)是一种可行的方法。

(注:从我的评论中可以清楚地看出,我首先不知道您指向最小值和最大值不同于 0,1 的情况。非规范化数字具有均匀分布的属性。因此,您可以通过以下方式获得等分布:将 53 位映射到尾数。接下来您可以使用浮点运算,因为它在机器精度方面是正确的。如果您使用反向映射,您将恢复等分布。

有关此问题的另一个方面,请参阅此问题:Scaling Intuniform random range into Double one