Divisiblity of 5 without using % and / operator
how to check whether a number is divisible by 5 or not without using % and / operator. I want a quickest algorithm for this problem.
Solution 1:
A good starting point is to look into how division can be accomplished with multiplication and bit-shifts. This question is one place to look.
In particular, you can follow the attached post to hit upon the following strategy. First, "divide by 5" using multiplication and bit-shifts:
int32_t div5(int32_t dividend) {
int64_t invDivisor = 0x33333333;
return 1 + (int32_t) ((invDivisor * dividend) >> 32);
}
Then, take the result and multiply by 5:
int result = div5(dividend) * 5;
Then, result == dividend
if and only dividend
is divisible by 5.
if(result == dividend) {
// dividend is divisible by 5
}
else {
// dividend is not divisible by 5
}
Solution 2:
There are two reasons I can see for wanting such an algorithm: (1) homework, or (2) writing efficient code for a microcontroller which does not have efficient division instructions. Assuming your reason is the second, but allowing for the possibility that it might be the first, I won't give you a full solution, but will suggest that if you divide your number into chunks that are a multiple of four bits each, the sum of all those chunks will be divisible by five only if the original number was; note that when performing such computation you must either avoid overflows or else add to your result the number of overflows that have occurred. I don't know any efficient way to do the latter in C, but in many machine languages it is easy. As a simple example, on the 8051 if one had a 32-bit integer, one could so something like:
mov a,Number ; Byte 0
add a,Number+1 ; Byte 1
adc a,Number+2 ; Byte 2, plus carry from last add
adc a,Number+3 ; Byte 3, plus carry from last add
adc a,#0 ; Add in carry, if any (might overflow)
adc a,#0 ; Add in carry, if any (can't overflow)
Note that in the machine code, adding the carries back into the number is much faster than performing 16-bit math would be.
Once the value has been reduced to the range 0-255, one could add the upper four bits to the lower 4 bits to get a value in the range 0 to 30. One could either test for the seven such values that are multiples of five, or work to reduce the number of possible values further [e.g. if the value is at least 15, subtract 15; if at least 10, subtract 10; if 5, subtract five; if zero, it's a multiple of five].
Solution 3:
Let's represent the number in base 2. We have:
abcdefgh*101 = ABCDEFGHIJ
or
+abcdefgh00
+ abcdefgh
----------
ABCDEFGHIJ
We are given ABCDEFGHIJ
and want to find abcdefgh
.
If you alternately - and + ABCDEFGH
with its successive rightshift-by-2, you will get...
+ ABCDEFGH
- ABCDEF
+ ABCD
- AB
-----------
+ abcdefgh
+ abcdef
- abcdef
- abcd
+ abcd
+ ab
- ab
-----------
abcdefgh
The answer!
Solution 4:
It finally got unlocked, so I can explain my comment, which incidentally turns out to generate better code than GCC does for x % 5 == 0
. See here, fill in
#include <stdint.h>
bool divisible_by_5(uint32_t x)
{
return x % 5 == 0;
}
bool divisible_by_5_fast(uint32_t x)
{
return x * 0xCCCCCCCD <= 0x33333333;
}
I'll assume unsigned input, because the OP suggested an algorithm that only works with positive input. This method can be extended to signed input, but it's a little messy.
0xCCCCCCCD
is the modular multiplicative inverse of 5, modulo 232. Multiplying a multiple of k (for example, n * k
) by the (modular) multiplicative inverse is equivalent to dividing by k, because
(n * k) * inv(k) =
// use associativity
n * (k * inv(k)) =
// use definition of multiplicative inverse
n * 1 =
// multiplicative identity
n
Modulo powers of two, a number has a modular multiplicative inverse iff it is odd.
Since multiplying by an odd number is invertible and is actually a bijection, it can't map any non-multiples of k to the 0 - (232-1)/k range.
So when it's outside that range, it can't have been a multiple of k.
0x33333333
is (232-1)/5, so if x * 0xCCCCCCCD
higher, x
can't have been a multiple of 5.