Fast divisibility tests (by 2,3,4,5,.., 16)?

后端 未结 16 2196
轻奢々
轻奢々 2020-12-05 00:14

What are the fastest divisibility tests? Say, given a little-endian architecture and a 32-bit signed integer: how to calculate very fast that a number is divisible by 2,3,4,

16条回答
  •  我在风中等你
    2020-12-05 00:56

    One thing to consider: since you only care about divisibility up to 16, you really only need to check divisibility by the primes up to 16. These are 2, 3, 5, 7, 11, and 13.

    Divide your number by each of the primes, keeping track with a boolean (such as div2 = true). The numbers two and three are special cases. If div3 is true, try dividing by 3 again, setting div9. Two and its powers are very simple (note: '&' is one of the fastest things a processor can do):

    if n & 1 == 0:
        div2 = true
        if n & 3 == 0: 
            div4 = true
            if n & 7 == 0: 
                div8 = true
                if n & 15 == 0:
                    div16 = true
    

    You now have the booleans div2, div3, div4, div5, div7, div8, div9, div11, div13, and div16. All other numbers are combinations; for instance div6 is the same as (div2 && div3)

    So, you only need to do either 5 or 6 actual divisions (6 only if your number is divisible by 3).

    For myself, i would probably use bits in a single register for my booleans; for instance bit_0 means div2. I can then use masks:

    if (flags & (div2+div3)) == (div2 + div3): do_6()

    note that div2+div3 can be a precomputed constant. If div2 is bit0, and div3 is bit1, then div2+div3 == 3. This makes the above 'if' optimize to:

    if (flags & 3) == 3: do_6()

    So now... mod without a divide:

    def mod(n,m):
        i = 0
            while m < n:
                m <<= 1
                i += 1
            while i > 0:
                m >>= 1
                if m <= n: n -= m
                i -= 1
         return n
    
    div3 = mod(n,3) == 0
    ...
    

    btw: the worst case for the above code is 31 times through either loop for a 32-bit number

    FYI: Just looked at Msalter's post, above. His technique can be used instead of mod(...) for some of the primes.

提交回复
热议问题