You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用加法和移位实现模t余r的n位随机数生成?

用加法+移位实现模t余r的均匀n位随机数

核心思路

要避开效率低下的长除法,我们可以通过预计算移位近似逆元替代x//t的计算,再结合移位、加法完成后续操作,最终得到满足结果 ≡ r mod t的均匀分布n位随机数。

1. 预计算关键参数

针对给定的t,先确定两个参数:

  • k:取n位整数的总位数(比如uint64_t对应64)
  • m:预计算一个近似等于2^k / t的值,可通过移位+加法的牛顿迭代法得到,全程不用除法
    同时预计算阈值threshold = (2^k) % t,用于后续拒绝采样保证计算精确性。

2. 拒绝采样过滤无效值

拿到随机数x后,先判断:如果x >= 2^k - threshold,直接丢弃这个x,重新生成新的随机数。这一步是为了确保剩下的x用移位+加法算出的商是精确的,避免近似误差。

3. 用移位+加法计算商q

原本的q = x//t,可以通过q = (x * m) >> k计算。如果要彻底禁用乘法(仅用加法+移位),可以把m拆成2的幂次之和(比如m = 2^a + 2^b + ...),将x*m转化为(x<<a) + (x<<b) + ...,再右移k位得到q。

4. 生成最终结果

计算q*t时,同样把t拆成2的幂次之和(比如t=10=2^3+2^1),将q*t转化为(q<<3) + (q<<1),最后加上r就得到符合要求的结果。

特殊情况优化:t是2的幂

如果t是2的幂(比如t=2^s),直接简化操作:

  • q = x >> s(移位直接替代除法)
  • result = (q << s) + r
    此时效率最高,无额外计算开销。

示例代码(uint64_t)

假设t为已知常量,预计算好m和threshold:

#include <stdint.h>

// 你的n位随机数生成器
uint64_t get_random_uint64();

// 预计算参数:替换为对应t的实际值
#define PRECOMPUTED_M 0x...
#define PRECOMPUTED_THRESHOLD 0x...

uint64_t gen_mod_r(uint64_t r) {
    uint64_t x;
    // 拒绝采样,保证计算精确
    do {
        x = get_random_uint64();
    } while (x >= (1ULL << 64) - PRECOMPUTED_THRESHOLD);

    // 用移位加法计算q = x//t(示例:m=2^60 + 2^58)
    uint64_t q = ((x << 60) + (x << 58)) >> 64;

    // 用移位加法计算q*t(示例:t=2^3 + 2^1=10)
    uint64_t qt = (q << 3) + (q << 1);
    return qt + r;
}

均匀性说明

拒绝采样过滤了会导致计算误差的x区间,避免了直接模运算带来的分布偏斜;精确计算的q保证每个符合≡r mod t的n位整数被选中的概率完全一致。

内容的提问来源于stack exchange,提问作者user3563894

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 02:45:07