Modulus operator is costly.
The modulus operator (%) in various languages is costly operation. Ultimately every operator/operation must result in processor instructions. Some processors won’t have modulus instruction at hardware level, in such case the compilers will insert stubs (predefined functions) to perform modulus. It impacts performance.
There is simple technique to extract remainder when a number is divided by another number (divisor) that is power of 2? A number that is an exact power of 2 will have only one bit set in it’s binary representation. Consider the following powers of 2 and their binary representations
2 – 10
4 – 100
8 – 1000
16 – 10000
Note those zeros in red color, they contribute to remainder in division operation. We can get mask for those zeros by decrementing the divisor by 1.
Generalizing the above pattern, a number that can be written in 2n form will have only one bit set followed by n zeros on the right side of 1. When a number (N) divided by (2n), the bit positions corresponding to the above mentioned zeros will contribute to the remainder of division operation. An example can make it clear,
N = 87 (1010111 – binary form)
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
Modulus operation over exact powers of 2 is simple and faster bitwise ANDing. This is the reason, programmers usually make buffer length as powers of 2.
Note that the technique will work only for divisors that are powers of 2.
Implementation of circular queue (ring buffer) using an array. Omitting one position in the circular buffer implementation can make it easy to distinguish between full and empty conditions. When the buffer reaches SIZE-1, it needs to wrap back to initial position. The wrap back operation can be simple AND operation if the buffer size is power of 2. If we use any other size, we would need to use modulus operation.
Per experts comments, premature optimization is an evil. The optimization techniques provided are to fine tune your code after finalizing design strategy, algorithm, data structures and implementation. We recommend to avoid them at the start of code development. Code readability is key for maintenance.
Thanks to Venki for writing the above article. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
- Compute modulus division by a power-of-2-number
- Space optimization using bit manipulations
- Check a number is odd or even without modulus operator
- Count number of bits to be flipped to convert A to B | Set-2
- Count Set-bits of number using Recursion
- Count smaller elements on right side and greater elements on left side using Binary Index Tree
- Equal Sum and XOR of three Numbers
- Find the number of pair of Ideal nodes in a given tree
- Bit manipulation | Swap Endianness of a number
- Find two integers A and B such that A ^ N = A + N and B ^ N = B + N
- Quadruplet pair with XOR zero in the given Array
- Find maximum xor of k elements in an array
- Alternate XOR operations on sorted array
- Minimum Bitwise OR operations to make any two array elements equal