模量运算符是昂贵的。
各种语言中的模数运算符(%)是昂贵的运算。最终,每个运算符/操作都必须得到处理器指令。一些处理器在硬件级别上没有模数指令,在这种情况下,编译器将插入存根(预定义函数)以执行模数。它影响性能。
当一个数字除以2的幂的另一个数字(除数)时,有一种简单的技术可以提取余数。精确为2的幂的数字在其二进制表示形式中将仅设置一位。考虑以下2的幂及其二进制表示
2 – 1 0
4 – 1 00
8 – 1000
16 – 0000
注意那些红色的零,它们会导致除法运算的余数。我们可以通过将除数减1来获得这些零的掩码。
概括上述模式,可以以2 n形式写入的数字将只设置一个位,然后在1的右侧设置n个零。当数字(N)除以(2 n )时,位位置对应于上述零将有助于除法运算的其余部分。一个例子可以清楚地说明,
N = 87(1010111 –二进制形式)
N%2 = N&(2-1)= 1010111&1 = 1 = 1
N%4 = N&(4-1)= 1010111&11 = 11 = 3
N%8 = N&(8-1)= 1010111&111 = 111 = 7
N%16 = N&(16-1)= 1010111&1111 = 111 = 7
N%32 = N&(32-1)= 1010111&11111 = 10111 = 23
精确运算2的幂的模运算很简单,并且按位ANDing更快。这就是原因,程序员通常使缓冲区长度为2的幂。
请注意,该技术仅适用于2的幂的除数。
一个例子:
使用数组实现循环队列(环形缓冲区)。在循环缓冲区实现中省略一个位置可以轻松区分满和空条件。当缓冲区达到SIZE-1时,它需要回绕到初始位置。如果缓冲区大小是2的幂,则回卷操作可以是简单的AND操作。如果我们使用任何其他大小,则需要使用模运算。
笔记:
根据专家的评论,过早的优化是邪恶的。提供的优化技术是在最终确定设计策略,算法,数据结构和实现之后,对您的代码进行微调。我们建议在代码开发开始时避免使用它们。代码可读性是维护的关键。