我正在寻找一种在开放区间(0,1)上生成随机浮点数的有效方法。我目前有一个RNG,它在闭合闭合间隔[0,(2 ^ 32)-1]上生成随机整数。我已经在区间[0,1)上创建了一个半开浮点RNG,只需将整数RNG的结果乘以1 /((2 ^ 32)-1)而不是除以(2 ^ 32) -1因为它效率低。
我目前在间隔(0,1)上生成数字的方式是使用如下所示的条件语句:
float open_open_flt = (closed_open_flt==0) ? closed_open_flt : FLT_MIN;
不幸的是,这是非常低效的,因为它是控制代码,我觉得它引入了一些偏见。
有人可以建议替代方案吗?
答案 0 :(得分:4)
你已经在那里了。
当前发电机产生的两个浮子之间的最小距离是1 /(2 ^ 32)。
所以,你的发电机正在有效地产生 [0,1-1 /(2 ^ 32)] 。
1 /(2 ^ 32)大于FLT_MIN。
因此,如果您将FLT_MIN添加到您的生成器,
float open_open_flt = FLT_MIN + closed_open_flt;
你将获得 [FLT_MIN,1-(1 /(2 ^ 32))+ FLT_MIN] ,它可用作(0,1)生成器。
答案 1 :(得分:3)
由于实际观察0概率的概率非常小,并且检查数字是否等于0是最便宜的(与加法或乘法相比),我会重复重新生成随机数,直到它不等于0
答案 2 :(得分:2)
鉴于从[0,2 32 ]中随机选择的样本x
,我建议使用:
0x1.fffffep-32 * x + 0x1p-25
推理:
x
在舍入之前产生略小于1-2 -25 ,因此它舍入到小于1的最大float
,这是1-2 -24 。如果我们做得更大,一些值将舍入为1,这是我们不想要的。如果我们把它做得更小,那么更少的值将会变为1-2 -24 ,因此它的代表性将低于我们想要的值(更多内容见下文)。x
产生2 -25 。这会产生一些对称性:如上所述,在舍入之前,分布被迫在高侧1-2 -25 处停止,因此我们使其在底部对称,停在0 + 2 < SUP> -25 。在某种程度上,就好像我们将宽度为2 -24 的区间中的实数行合并,然后移除以0和1为中心的区间(延伸2 -25 这些数字的任何一方)。float
值会显示在分档中,因为float
的分辨率会有所不同。它在0附近更精细,在1附近更粗。通过这种布置,每个箱子大致均匀地表示,但是下部箱子将具有更多的样本,每个箱子具有更低的概率。总体分布保持一致。正如您所看到的,浮点格式强制分布中的一些不规则性从0到1.此问题已在其他Stack Overflow问题中提出,但据我所知,从未进行过彻底讨论。是否适合您的目的,如上所述留下这些违规行为取决于您的申请。
潜在变化:
float
格式更精细的更精细。double
。然后是从原始x
值到浮点值的1-1映射,您可以根据需要接近0和1。另外,与ElKamina’s answer相反,浮点比较(甚至为零)通常不比加法快。比较需要对结果进行分支,这在许多现代CPU中都是一个问题。
答案 3 :(得分:1)
我正在寻找一种在开放区间(0,1)上生成随机浮点数的有效方法。我目前有一个RNG,它在闭合闭合间隔[0,(2 ^ 32)-1]上生成随机整数。我已经在区间[0,1)上创建了一个半开浮点RNG,只需将整数RNG的结果乘以1 /((2 ^ 32)-1)
这意味着您的生成器“尝试”生成2 ^ 32个不同的值。问题是, float 类型长度为4个字节,因此总体上定义的值不到2 ^ 32个。确切地说,间隔[1/2,1]上只能有2 ^ 23个值。根据您的需要,它可能是一个问题。
您可能希望使用滞后Fibonacci生成器(wiki)进行迭代
这已经从[0,1)产生数字,因为初始值属于该间隔,并且可能足以满足您的需要。