根据您的编辑,这里似乎存在一个误解。通过“统一的4位整数”,您似乎想到了以下内容:
- 从0开始。
- 生成一个随机位。如果是1,则加1,否则减1。
- 重复第2步三次。
- 输出结果数字。
尽管随机位生成器可能会生成每个结果都有同样可能性的位,每个4位块也可能像任何其他块一样具有同样的可能性来进行随机生成,但每个块中的位数并不是均匀分布的。
您需要什么范围的整数?假设您正在生成4位整数。您是否希望获得[-4, 4]的范围,就像问题中的4位随机游走一样,还是希望获得[-8, 7]的范围,这是当您将4位比特块视为二进制补码整数时所得到的?
如果是前者,则随机游走不会生成均匀分布,并且您需要以不同的方式解决该问题。
在这种情况下,要在范围[-4, 4]内生成均匀分布的随机数,请执行以下操作:
- 获取随机比特发生器的4位,并将其视为[0,15)中的整数;
- 如果整数大于8,请执行步骤1。
- 从整数中减去4并输出它。
此算法使用拒绝抽样,但是是可变时间的(因此不适用于任何可以利用安全攻击中的时间差异的情况)。其他范围的数字也是以类似的方式生成的,但详细信息过于复杂,无法在此答案中描述。请参阅我的文章
随机数生成方法了解详情。
根据您向我展示的代码,您构建
byte
、
int
和
long
的方法容易出错。例如,构建8位字节以实现您想要的结果的更好方法如下所示(请记住,我对Kotlin不是很熟悉,因此语法可能有误):
val i = 0
val b = 0
for (i = 0; i < 8; i++) {
b = b << 1;
if (bitStringBuilder[i] == '1') {
b = b | 1;
} else {
b = b | 0;
}
}
value = (b as byte) as T
此外,如果
MediatorLiveData
不是线程安全的,那么使用
StringBuilder
收集位的方法也不是线程安全的(特别是因为
StringBuilder
不是线程安全的)。
您建议的方法,将布尔发生器的八个位组合成一个统一的整数,在理论上是可行的。但是,在实践中存在几个问题:
- 您没有提到它是什么类型的硬件。在大多数情况下,除非硬件是所谓的真随机数生成器,否则硬件不太可能生成均匀的随机布尔位。例如,硬件可能会生成均匀分布的位,但具有周期性行为。
- 熵表示预测生成器产生的值相对于理想随机值有多难。例如,具有32位熵的64位数据块与理想随机32位数据块一样难以预测。表征硬件设备的熵(或产生不可预测值的能力)远非易事。除其他事项外,这涉及必须在适用于硬件的操作条件的全部范围内进行的熵测试(例如,温度、电压)。
- 大多数硬件不能产生均匀的随机值,因此通常需要执行额外的步骤,称为随机性提取、熵提取、去偏、白化或去斜,将硬件生成的值转换为均匀分布的随机数。但是,如果先表征硬件的熵(请参见上一个问题),则效果最佳。
- 最后,您仍然需要测试整个过程是否为您的目的提供了“足够随机”的数字。有几种统计测试试图这样做,例如NIST的统计测试套件或TestU01。
更多信息,请参见“非确定性来源和种子生成”。
在您编辑此页面之后,似乎您正在错误的方法解决问题。要生成均匀的随机数,您不应该
添加均匀分布的随机位(例如,
bit() + bit() + bit()
),而应该
连接它们(例如,
(bit() << 2) | (bit() << 1) | bit()
)。但是,同样地,由于我上述提到的原因,这在实践中并不可行。