【问题标题】:Does anyone know a better way for modulo on bits? [duplicate]有谁知道对位取模的更好方法? [复制]
【发布时间】:2016-08-30 09:52:20
【问题描述】:

我有 2 个大数字,一个大约 4096 位,另一个 2048 位,存储在一个结构中:

 typedef uint32_t word;
 typedef struct BigNumber {
     word words[128];
 } BigNumber;

我必须对这些取模,我能想到的唯一方法是多次减去,但这需要一些时间。

有人知道更好的方法吗?

【问题讨论】:

  • 不幸的是我不能使用 MGP 库,而且他们的代码对我来说并不是真正可重用的
  • 它是关于任意数模还是具有一些幂 2 数的模块(将高位设置为零)?
  • @grek40 任意,除了长度没有特殊规定
  • @ZangMingJie:不是真正的复制品。这是一个 128*32 = 4096 位整数。但同样的原则确实适用。

标签: c math biginteger modulo


【解决方案1】:

代码基于@caf 并经过我的更正。让 OP 编写 4 个辅助函数。

void BigNumber_Shift_Right(BigNumber *x);
void BigNumber_Shift_Left(BigNumber *x);
int BigNumber_Compare(const BigNumber *a, const BigNumber *b);
void BigNumber_SubtractEqual(BigNumber *a, const BigNumber *b);

void BigNumber_ModHalfSizeEqual(BigNumber *A, const BigNumber *B) {
  BigNumber X = *B;
  BigNumber AHalf = *A;
  BigNumber_Shift_Right(&AHalf);

  while (BigNumber_Compare(&X, &AHalf) <= 0) {
    BigNumber_Shift_Left(&X);
  }

  while (BigNumber_Compare(A, B) >= 0) {
    if (BigNumber_Compare(A, &X) >= 0) {
      BigNumber_SubtractEqual(A, &X); 
    }
    BigNumber_Shift_Right(&X);
  }

  // mod is in A
}

【讨论】:

    【解决方案2】:

    计算 m % n:

    modulus(m, n) {
      if (m < n) return m
      elif (m < (n<<1)) return m - n
      else return modulus((modulus(m>>1, n)<<1 + m&1), n)
    }
    

    【讨论】:

    • 是的,这是一个重复减法的模型,我很好奇有没有什么特殊的规则可以提高算法的效率
    • @PopoviciSebi 这使用了特殊规则,它不仅仅是“不断减法,直到宇宙热死”。注意变化。
    • @Harold 你能解释一下我不确定我理解背后的数学概念吗
    • 我在stackoverflow.com/questions/2566010/… 找到了更好的实现和解释,我会将问题标记为重复
    • 好的,谢谢,我想这可能有用
    【解决方案3】:

    你可以用 a 除以 b 得到一个整数 x。现在从 a 中减去 x 并得到模数。使用任意除数,您将无法绕过除数。对于大除数,这可能比多次减法更快,但除法仍然很昂贵。

    对于如此大的数字,您可能还必须手动实现除法算法。有一个,它同时产生 qoutient 和余数(模数),但我现在记不起它的名字了。

    【讨论】:

    • 对不起,我试过这个,但几乎是同一时间,而且占用更多内存
    猜你喜欢
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-20
    相关资源
    最近更新 更多