【发布时间】:2011-09-12 01:18:33
【问题描述】:
我正在使用 RNG 加密提供程序以真正幼稚的方式生成范围内的数字:
byte[] bytes = new byte[4];
int result = 0;
while(result < min || result > max)
{
RNG.GetBytes(bytes);
result = BitConverter.ToInt32(bytes);
}
当范围足够宽以致有相当大的机会获得结果时,这很好,但今天早些时候我遇到了一个范围足够小(在 10,000 个数字内)以至于可能需要一段时间的情况。
所以我一直在尝试寻找一种更好的方法来实现体面的分布,但速度更快。但现在我正在研究我在学校根本没有做过的更深层次的数学和统计,或者至少我已经忘记了!
我的想法是:
- 获取最小值和最大值的最高设置位位置,例如4 为 3,17 为 5
- 从 prng 中选择可能至少包含高位的字节数,例如在这种情况下为 1 个 8 位
- 查看是否设置了允许范围 (3-5) 中的任何高位
- 如果是,则将其转换为最高位并包括高位的数字
- 如果该数字介于 min 和 max 之间,则返回。
- 如果之前的任何测试失败,请重新开始。
就像我说的那样,这可能非常幼稚,但我确信它会比当前实现更快地返回一个狭窄范围内的匹配项。我现在不在电脑前,所以无法测试,明天早上英国时间会这样做。
当然速度不是我唯一关心的问题,否则我只会使用 Random (如果有人足够友善,则需要在那里打几个刻度才能正确格式化 - 他们不在Android 键盘!)。
我对上述方法的最大担忧是我总是丢弃由 prng 生成的多达 7 位,这似乎很糟糕。我想到了将它们考虑在内的方法(例如简单的加法),但它们看起来非常不科学!
我知道 mod 技巧,你只需要生成一个序列,但我也知道它的弱点。
这是一个死胡同吗?最终,如果最好的解决方案是坚持当前的实现,我只是觉得一定有更好的方法!
【问题讨论】:
-
while(result < min && result > max) { }我想这两个条件操作数之间应该有||运算符而不是&&。 -
是的 - 刚刚编辑。真不敢相信这不是早点发现的。