【发布时间】:2021-07-07 18:29:08
【问题描述】:
我一直在为随机数生成创建一个精简的库,并且一直在努力生成一个范围内的有符号整数。
无符号整数很简单,我已经实现了 Lemire 的去偏整数乘法方法。但是,它不容易扩展到有符号整数:
impl<R: Rng> RandomRange<R> for u64 {
fn random_range<B: RangeBounds<Self>>(r: &mut R, bounds: B) -> Self {
const BITS: u128 = core::mem::size_of::<u64>() as u128 * 8;
let lower = match bounds.start_bound() {
Bound::Included(lower) => *lower,
Bound::Excluded(lower) => lower.saturating_add(1),
Bound::Unbounded => <u64>::MIN,
};
let upper = match bounds.end_bound() {
Bound::Included(upper) => upper.saturating_sub(lower).saturating_add(1),
Bound::Excluded(upper) => upper.saturating_sub(lower),
Bound::Unbounded => <u64>::MAX,
};
let mut value = Self::random(r);
let mut m = (upper as u128).wrapping_mul(value as u128);
if (m as u64) < upper {
let t = (!upper + 1) % upper;
while (m as u64) < t {
value = Self::random(r);
m = (upper as u128).wrapping_mul(value as u128);
}
}
(m >> BITS) as u64 + lower
}
}
如何在有符号整数的最小/最大范围内实现大部分去偏随机数生成?
【问题讨论】:
-
另见我的部分:
RNDINTRANGE. -
不清楚将算法转换为有符号数字有什么困难。您知道范围的宽度和范围的开始。你能不生成一个宽度相同的无符号范围,然后将结果值移到开头吗?
-
@Shepmaster:等等,你是对的......给我一点,我会试着自己回答这个问题。
-
我现在正在为整个 i32-u32 转换而苦苦挣扎,呃。