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



在C和c++中,我想将一个有符号整数除以一个正整数,并对其进行除法和模取,使div趋向于负无穷,并且模取总是返回非负。

对于分区,我有:

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

,这是从这个问题的答案中得到的。

对于mod我有:

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"one_answers"余数"有什么区别?也处理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;
}

像@Goswin von Brederlow当b > 0

最新更新