re implement modulo using bit shifts?

后端 未结 5 1667
情歌与酒
情歌与酒 2021-02-07 16:10

I\'m writing some code for a very limited system where the mod operator is very slow. In my code a modulo needs to be used about 180 times per second and I figured that removing

5条回答
  •  眼角桃花
    2021-02-07 16:30

    What you can do with simple bitwise operations is taking a power-of-two modulo(divisor) of the value(dividend) by AND'ing it with divisor-1. A few examples:

    unsigned int val = 123; // initial value
    unsigned int rem;
    
    rem = val & 0x3; // remainder after value is divided by 4. 
                     // Equivalent to 'val % 4'
    rem = val % 5;   // remainder after value is divided by 5.
                     // Because 5 isn't power of two, we can't simply AND it with 5-1(=4). 
    

    Why it works? Let's consider a bit pattern for the value 123 which is 1111011 and then the divisor 4, which has the bit pattern of 00000100. As we know by now, the divisor has to be power-of-two(as 4 is) and we need to decrement it by one(from 4 to 3 in decimal) which yields us the bit pattern 00000011. After we bitwise-AND both the original 123 and 3, the resulting bit pattern will be 00000011. That turns out to be 3 in decimal. The reason why we need a power-of-two divisor is that once we decrement them by one, we get all the less significant bits set to 1 and the rest are 0. Once we do the bitwise-AND, it 'cancels out' the more significant bits from the original value, and leaves us with simply the remainder of the original value divided by the divisor.

    However, applying something specific like this for arbitrary divisors is not going to work unless you know your divisors beforehand(at compile time, and even then requires divisor-specific codepaths) - resolving it run-time is not feasible, especially not in your case where performance matters.

    Also there's a previous question related to the subject which probably has interesting information on the matter from different points of view.

提交回复
热议问题