Is there any way to write “mod 31” without modulus/division operators?

后端 未结 5 1000
我在风中等你
我在风中等你 2020-12-03 16:02

Getting the modulus of a number can be easily done without the modulus operator or divisions, if your operand is a power of 2. In that case, the following formula holds:

5条回答
  •  北海茫月
    2020-12-03 16:25

    If you want to get the modulus of dividing by a denominator d such that d = (1 << e) - 1 where e is some exponent, you can use the fact that the binary expansion of 1/d is a repeating fraction with bits set every e digits. For example, for e = 5, d = 31, and 1/d = 0.0000100001....

    Similar to rici’s answer, this algorithm effectively computes the sum of the base-(1 << e) digits of a:

    uint16_t mod31(uint16_t a) {
        uint16_t b;
        for (b = a; a > 31; a = b)
            for (b = 0; a != 0; a >>= 5)
                b += a & 31;
        return b == 31 ? 0 : b;
    }
    

    You can unroll this loop, because the denominator and the number of bits in the numerator are both constant, but it’s probably better to let the compiler do that. And of course you can change 5 to an input parameter and 31 to a variable computed from that.

提交回复
热议问题