有效地在开放区间(0,1)上生成随机数

时间:2013-07-30 18:49:11

标签: c algorithm random intervals random-sample

我正在寻找一种在开放区间(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; 

不幸的是,这是非常低效的,因为它是控制代码,我觉得它引入了一些偏见。

有人可以建议替代方案吗?

4 个答案:

答案 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 这些数字的任何一方)。
  • 我们保留的每个bin包含大约相同数量的样本值。但是,不同的float值会显示在分档中,因为float的分辨率会有所不同。它在0附近更精细,在1附近更粗。通过这种布置,每个箱子大致均匀地表示,但是下部箱子将具有更多的样本,每个箱子具有更低的概率。总体分布保持一致。
  • 我们可以延长低端,使其接近于零。但是,对于(0,½)中的大多数 d ,(0, d )中的样本将多于(1- d ,1),因此分布将是不对称的。

正如您所看到的,浮点格式强制分布中的一些不规则性从0到1.此问题已在其他Stack Overflow问题中提出,但据我所知,从未进行过彻底讨论。是否适合您的目的,如上所述留下这些违规行为取决于您的申请。

潜在变化:

  • 对所有样本进行量化,使它们以规则的间隔出现,2 -24 ,而不是float格式更精细的更精细。
  • 在舍入之前允许值接近1,但在舍入后将它们转换为1-2 -24 ,并降低底部端点以匹配。这减少了排除在0和1左右的段,代价是增加了聚集到1-2 -24 的值的数量,因为分辨率不够精确,无法进行更多区分。
  • 切换到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)进行迭代 iteration formula from russian wiki
这已经从[0,1)产生数字,因为初始值属于该间隔,并且可能足以满足您的需要。