【问题标题】:Generating random integers uniformly in log space在对数空间中均匀生成随机整数
【发布时间】:2016-10-17 09:32:51
【问题描述】:

我想生成在日志空间中均匀分布的随机整数。也就是说, 的值的对数将是均匀分布的。

一个正态均匀分布的 unsigned int 将有 75% 的大小超过 10 亿,大约 99.98% 超过 100 万,因此小值的代表性不足。例如,来自日志空间的统一值将在 4-8 范围内具有与 256-512 相同数量的值。

暂时忽略负值,我能想到的一种方法是:

Random r = new Random();
return (int)Math.pow(2, r.nextDouble() * 31);

这应该会生成一个 31 位日志均匀分布。不过它不会很快,在那里有一个pow() 操作并引入浮点值来生成整数有点难闻。此外,Random.nextDouble() 丢失了double 的很多范围,我不清楚这段代码是否甚至可以生成所有 2^31-1 正整数值。

欢迎提供更好的解决方案。


下面有两种类似的解决方案,它们都涉及用随机位填充整数,然后将随机位数向右移动。比如:

int number = rand.nextInt(Integer.MAX_VALUE) >> rand.nextInt(Integer.SIZE);

这有两种类型的偏见:

逐步偏差

这会产生一种逐步对数分布值,而不是平滑值。特别是,在 [0,31] 中右移一个随机值,意味着有 31 个等概率的整数“大小”,并且该范围内的每个值都是等概率的。由于范围 N 中有 2^N 个值,因此一个范围内的值的概率是下一个范围内的值的两倍 - 因此您可以得到范围之间的日志行为,但范围本身是平坦的。

我不知道摆脱这种偏见的简单方法。

高位偏差

出现第二种形式的偏差是因为 MSB 并不总是 1(例如,即使移位量为 10,也不一定会产生31-10=21 位值,这会产生额外的失真。实际上,范围重叠. 值 1 不仅存在 (p(1)=.5) 移位量为 30,而且移位量为 29 (p(1)=0.25)、28 (p(1)=.125) ,依此类推。对于较小的值(即,如果仅查看 30 和 29 的移位量,1 似乎比 2 的可能性高 3 倍,而不是 2 倍的预测值,但是一旦您查看在更多值时它会收敛。但是,它不会因大值而抵消,这就是为什么您看到 20:32207 存储桶比@sprinter 的答案中的其他存储桶小。

我认为这种形式的偏差可以很容易地通过将最高位强制为零来消除,因此类似于:

(r.nextInt(0x40000000) | 0x40000000) >> r.nextInt(31)

这还有一些其他的调整 - rand 的最大值为 2^30,这更快(nextInt(int) 代码中 2 的幂的特殊情况),因为我们从不想要第二个 MSB 位无论如何设置(我们强制它为1)。这也消除了一个微观的额外偏差来源,即永远无法生成 Integer.MAX_VALUE,因此完整表示中缺少一个值。

它移动 [0,31) 位,因此您永远不会得到零,如果您也想要零,请将其更改为移动 [0,32) 位,您将得到频率等于 1 的零(技术上不记录- 不再分发,但在许多情况下很有用)。另一种方法是从最终值中减去一个以得到零(以永远不会得到 Integer.MAX_VALUE 为代价)。

【问题讨论】:

  • 这是您在分布上提出的一个非常好的观点 - 并且通过对我回答中的偏差的解释进行了深思熟虑。也许有一个解决方案可以根据分布中的概率设置每个位。将尝试创建一个 - 尽管我不相信它会比你的更有效。
  • 不,抱歉,无法根据每个位被设置的概率找到一种简单的方法来执行此操作。它的数学并不像你知道的那样简单。我认输。
  • 我认为如果你的 P(X = x) 与 1/x 成正比,你就会得到这个。但我还没有找到实现这一目标的好方法。

标签: java math random distribution


【解决方案1】:

提供的错误答案仅供参考。由于问题中给出的原因,这不满足 OP 的要求。

int number = rand.nextInt(Integer.MAX_VALUE) >> rand.nextInt(Integer.SIZE);

我对此的非正式测试似乎表明存在预期的偏差。我以这种方式生成了 100 万个数字,并具有以下日志分布(忽略零)

0:46819
1:47045
2:40663
3:44001
4:45306
5:43802
6:46447
7:43355
8:47366
9:42747
10:46387
11:43899
12:45179
13:45496
14:44431
15:46751
16:43055
17:47127
18:41243
19:41837
20:32207
21:11965

【讨论】:

  • 是的,这是一个合理的近似值。它不是平滑的日志分布,而是逐步分布的。即,MSB 为 0x100 的所有值的可能性均等,MSB 为 0x200 的所有值的可能性均等 - 但较小的值应该更有可能。因此,如果您将其绘制得足够精细,分布函数将具有阶梯形状。当第一个随机值的 MSB 不是 1 时,还有一个额外的偏差。例如,0x1 应该是 0x2 的 2 倍,但是我们有不同移位量的这些情况:
  • 我在关于这两种偏见的问题的末尾添加了一些细节。它还解释了为什么“20”存储桶非常小。
  • 别那么难回答!这是一个很好的近似值,就我的目的而言,它实际上“足够好”。
  • 我接受了这个答案,因为它很接近,并且是几个月后的唯一答案。未来的读者应该了解上述 cmets 中讨论的偏见来源。
猜你喜欢
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多