在 C 语言中,查看一个数是否可被另一个数整除的最佳方法是什么?我用这个:
if (!(a % x)) {
// this will be executed if a is divisible by x
}
反正有哪个更快吗?我知道做,即 130 % 13 将导致每 10 次做 130 / 13。所以有 10 个周期只需要一个(我只想知道 130 是否可以被 13 整除)。
谢谢!
在 C 语言中,查看一个数是否可被另一个数整除的最佳方法是什么?我用这个:
if (!(a % x)) {
// this will be executed if a is divisible by x
}
反正有哪个更快吗?我知道做,即 130 % 13 将导致每 10 次做 130 / 13。所以有 10 个周期只需要一个(我只想知道 130 是否可以被 13 整除)。
谢谢!
我知道做,即 130 % 13 将导致每 10 次做 130 / 13
梦呓。%
在我用过的任何处理器上都没有这样的事情。它执行130/13
一次,并返回剩余部分。
使用%
. 如果您的应用程序运行太慢,请对其进行分析并修复太慢的问题。
对于两个任意数,最好的检查方法是检查是否a % b == 0
. 模运算符根据硬件具有不同的性能,但是您的编译器可以比您更好地解决这个问题。模数运算符是通用的,您的编译器将为您运行的任何硬件找出最佳指令序列。
如果其中一个数字是常数,您的编译器可能会通过位移和减法的某种组合进行优化(主要针对 2 的幂),因为硬件 div/mod 比加法或减法慢,但在现代处理器上延迟(已经仅几纳秒)被大量其他性能技巧所隐藏,因此您不必担心。没有硬件通过重复除法计算模数(一些旧处理器通过重复位移和减法进行除法,但他们仍然为此使用专门的硬件,因此让硬件完成它仍然比尝试在软件中模拟它更快)。大多数现代 ISA 实际上在一条指令中计算除法和余数。
唯一可能有用的优化是除数是否为 2 的幂。然后,您可以使用&
屏蔽低位(通过除数 - 1)并检查结果是否为零。例如,检查是否a
可以被 8 整除,a & 7 == 0
是等价的。一个好的编译器会为你做这件事,所以坚持坚持使用%
.
在一般情况下,使用模运算符可能是最快的方法。有例外,特别是如果您对数字是否可以被 2 的幂整除感兴趣(在这种情况下可以使用按位运算),但如果您只使用%
. 对于任意值,您不太可能做得更好,例如13
.
另外,“每 10 次做 130 / 13”是什么意思?它做130 / 13
一次。这正是所需要的。
如果x
是一个常数,那么是的:
if (a * 0x4ec4ec4ec4ec4ec5 < 0x13b13b13b13b13b2) {
// this will be executed if a is divisible by 13
}
0x4ec4ec4ec4ec4ec5
是 13 的模乘逆(模 2 64),所以如果a
真的是 13 的倍数,那么乘积将小于 (2 64 /13)。(因为 a 是某个 integer 的 13 倍n
,并且n
必须适合 64 位字,这意味着它小于 2 64。)
这仅适用于 的奇数值x
。对于偶数(即y>0的 2 yy
的倍数),您可以将此测试与按位与测试相结合(最后一位a
应该为零。如果它们被除以a
2 y并继续进行乘法测试。)
这仅在 是一个常数时才值得x
,因为计算乘法逆比比整数除法更昂贵。
编辑:我也在假设a
并且x
没有签名。
当机器执行%
除法指令时,它会自动生成余数。
但是,请注意,如果其中一个数字为负数,%
则余数为负数。如果你只关心余数为零,这不是问题,但如果你碰巧在寻找另一个余数,比如 1,它真的会让你绊倒。