繁体   English   中英

高效/便携有符号整数模正整数返回非负数?

[英]Efficient/portable signed integer mod positive integer returning nonnegative?

在 C 和 C++ 中,我想将一个有符号整数除以一个正整数并对其进行取模,以使 div 向负无穷大舍入,并且取模始终返回非负数。

对于我有的部门:

int64_t SignedDiv(int64_t A_signed, int64_t B_positive) {
    return A_signed / B_positive - (A_signed % B_positive < 0);
}

这是从这个答案中获取的类似问题。

对于我拥有的模组:

int64_t SignedMod(int64_t A_signed, int64_t B_positive) {
   return A_signed - B_positive * SignedDiv(A_signed, B_positive);
}

这看起来很可怕。 有没有办法重写SignedMod以使其返回相同的东西(并且同样可移植)但效率更高?

这是godbolt上的编译输出:

https://godbolt.org/z/eeG93xh5f

这使用 clang -O3 在 x86_64 上保存 2 个操作码:

int64_t SignedMod2(int64_t A_signed, int64_t B_positive) {
   int64_t t = A_signed % B_positive;
   if (t < 0) t += B_positive;
   return t;
}

使用 gcc 或 clang -Os 消除了输出中的所有跳跃,这可能会更快一些。 我不知道 clang 在那里做什么用不必要的跳跃来炸毁代码长度。

mod 总是返回非负数。

从这个答案中得出: “mod”和“remainder”有什么区别? . 还处理b < 0极端情况 - 即使 OP 说b > 0

int modulo_Euclidean2(int a, int b) {
  if (b == 0) TBD_Code(); // perhaps return -1 to indicate failure?
  if (b == -1) return 0; // This test needed to prevent UB of `INT_MIN % -1`.
  int m = a % b;
  if (m < 0) {
    // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
    m = (b < 0) ? m - b : m + b;
  }
  return m;
}

b > 0时,就像@Goswin von Brederlow一样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM