introduction in general, on common processor machine, Integer multiplication is many times faster than division. So dividing a numerator n by a divisor d is mathematically equivalent to multiplication by the inverse of the divisor n / d = n * (1/d)
the faster remainder algorithm implemented in c is following(unsigned and signed):
1 2 3 4 5 6 7 8 9 10
uint32_t d = ...; // your divisor > 0
// c = ceil ( (1 < <64) / d ) ; we take L = N uint64_t c = UINT64_C (0xFFFFFFFFFFFFFFFF ) / d + 1;
// fastmod computes (n mod d) given precomputed c uint32_tfastmod( uint32_t n /* , uint64_t c, uint32_t d */) { uint64_t lowbits = c * n; return (( __uint128_t ) lowbits * d) >> 64; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14
int32_t d = ...; // your non - zero divisor in [ -2147483647 ,2147483647]
uint32_t pd = d < 0 ? -d : d; // absolute value , abs (d) // c = floor ( (1 < <64) / pd ) + 1; Take L = N + 1 uint64_t c = UINT64_C (0xFFFFFFFFFFFFFFFF ) / pd + 1 + (( pd & (pd -1) ) ==0 ? 1 : 0) ;
// fastmod computes (n mod d) given precomputed c int32_tfastmod( int32_t n /* , uint64_t c, uint32_t pd */) { uint64_t lowbits = c * n; int32_t highbits = (( __uint128_t ) lowbits * pd) >> 64; // answer is equivalent to (n <0) ? highbits - 1 + d : highbits return highbits - (( pd - 1) & (n >> 31) ) ; }
judge divisiablility
1 2 3 4 5 6 7 8 9
// calculate c for use in lkk_divisible uint64_tlkk_cvalue( uint32_t d) { return1 + UINT64_C (0xffffffffffffffff ) / d; } // given precomputed c, checks whether n % d == 0 boollkk_divisible( uint32_t n, uint64_t c) { // rhs is large when c ==0 return n * c <= c - 1; }
预览: