在C中,最好的方法是查看一个数字是否可以被另一个数除尽?

时间:2011-05-25 19:33:18

标签: c math optimization micro-optimization integer-division

在C中,最好的方法是查看一个数字是否可以被另一个数字整除?我用这个:

if (!(a % x)) {
// this will be executed if a is divisible by x
}

反正哪个更快?我知道这样做,即130%13将导致每10次做130/13。因此,只需要一个循环就有10个循环(我只想知道130是否可以被13整除)。

谢谢!

5 个答案:

答案 0 :(得分:25)

  

我知道这样做,即130%13将导致每10次130/13

梦呓。 %在我曾经使用的任何处理器上都没有这样的东西。它会130/13一次,并返回余数。

使用%。如果您的应用程序运行速度太慢,请对其进行分析并修复任何太慢的应用程序。

答案 1 :(得分:8)

对于两个任意数字,检查的最佳方法是检查是否a % b == 0。模数运算符具有基于硬件的不同性能,但您的编译器可以比您更好地解决这个问题。模数运算符是通用的,您的编译器将为您正在运行的任何硬件找出最佳的指令序列。

如果其中一个数字是常数,你的编译器可能会通过进行一些位移和减法的组合来优化(主要是2的幂),因为硬件div / mod比加法或减法慢,但在现代处理器上延迟(已经只有几纳秒)被大量其他性能技巧所隐藏,因此您无需担心它。没有硬件通过重复划分来计算模数(一些旧的处理器通过重复的位移和减法进行划分,但它们仍然使用专用硬件,因此硬件执行它比使用软件模拟它更快)。大多数现代ISA实际上都在一条指令中计算除法和余数。

可能有用的唯一优化是除数是2的幂。然后,您可以使用&来屏蔽低位(通过除数-1)并检查结果为零。例如,要检查a是否可被8整除,a & 7 == 0是等效的。一个好的编译器会为你做这个,所以坚持使用%

答案 2 :(得分:6)

在一般情况下,使用模运算符可能是最快的方法。有一些例外,特别是如果您对数字是否可以被2的幂整除感兴趣(在这种情况下,按位运算可用),但如果您只使用%,编译器应自动为您选择它们​​。对于13等任意值,您不太可能做得更好。

另外,“每10次做130/13”是什么意思?它只130 / 13一次。这正是所需要的。

答案 3 :(得分:3)

如果x是常数,那么是:

if (a * 0x4ec4ec4ec4ec4ec5 < 0x13b13b13b13b13b2) {
    // this will be executed if a is divisible by 13
}

0x4ec4ec4ec4ec4ec5modular multiplicative inverse的13(模2 64 ),所以如果a实际上是13的倍数,那么产品将小于(2 64 / 13)。 (因为a是整数n的13倍,而n必须符合64位字,这意味着它小于2 64 。)

这仅适用于x的奇数值。对于偶数(即y> 0的倍数为2 y ),您可以将此测试与按位AND测试结合使用(y的最后a位应为零如果他们然后将a除以2 y 并继续进行乘法测试。)

如果x是常量,这是值得的,因为计算乘法逆是比整数除法更贵。


修改:我还假设ax未签名。

答案 4 :(得分:0)

当机器执行%时,它只执行除法指令,并自动生成余数。

然而,请注意,如果其中一个数字为负数,%将给出负余数。 如果你只关心零的余数,这不是问题, 但是,如果你正在寻找另一个剩余部分,比如1,它真的会让你失望。