Division using bitwise operators
I spotted a post on stackoverflow and
saw this bizarre method to divide by 3 (What's the fastest way to divide an integer by 3?).
It says that: n/3 = (n * 0x55555556) >> 32. That is multiply by 0x55555556 and take the most significant 32 bits. This is true for n being a 32 bit number.
As I began digging the logic behind it I realised that this can be generalized. For instance if we consider n < 128; i.e. 7 bit wide then:
n/3 = (n * 0x56) >> 8.
So what's happening here ? Well, 0x56 = 86 = (258/3) and 258 is the first number bigger than 256 which is divisible by 3. Now,
2n = 258n - 256n
==> n = 129n - 128n for any n;
But if restrict n < 128; then 129n - 128n is same as quotient of (129n/128).
==> n = 129n/128; n < 128
==> n/3 = 43n/128; for n < 128
==> n/3 = 86n/256; n < 128
==> n/3 = (n * 0x56) >> 8;
It is amazing how this can be generalised to other divisions. For instance consider division by 5:
4n = 260n - 256n ==> n = 65n - 64n for all n
If n < 64; n = 65n/64
==> n/5 = 13n/64; n < 64
==> n/5 = (13 * n) >> 6;
similarly, n/5 = (52 * n) >> 8; n < 64
We can proceed on the same lines and derive that:
n/5 = 205n/1024 = (205*n) >> 10 for n < 1024
So; I tried to find a general rule to find n/a for any a ?
first find some power of two (say 2^m) which is one short of multiple of a (like 1024 in case of a = 5);
i.e. 2^m + 1 = ka; for some k
So the job is to figure out k while keeping m fixed (say 32) from: 2^m + 1 = ka. There can be multiple solutions to this; once m is fixed there will only be one.
Then; n/a = k*n >> m; for all n < 2^m
Now is this the way compiler works ? Using the formula generator provided by kol in one of the comments:
keeping m=32 and n=12; the formula generator gives:
a=3: n/3 = (1431655766 * n) >> 32
a=5: n/5 = (858993460 * n) >> 32
a=7: n/7 = (613566757 * n) >> 32
However, when I see my assembly output I get 1431655766, 1717986919 and -1840700269 respectively for dividing by 3, 5 and 7.
Moreover, if I change the data type to unsigned int then I get -1431655765, -858993459 and 613566757 respectively for 3,5 and 7.
As you can see; my prediction for divide by 3 is bang on but it fails for 5 and 7. it is interesting to see how closely they are related; but I am unable to explain it
Where have I went wrong in analysing what compiler does while dividing ?
The code from formula generator (by kol):
var $a = $("#a"),
$m = $("#m"),
$generate = $("#generate"),
$formula = $("#formula");
$generate.click(function () {
var a = +$a.val(),
m = +$m.val(),
m2 = 0,
k = 0;
if (isNaN(a) || a !== Math.floor(a) || a < 2 || a > Math.pow(2, 31) - 1) {
alert("Divisor \"a\" must be an integer between 2 and 2^32-1");
return;
}
m2 = Math.pow(2, m);
k = Math.ceil(m2 / a);
$formula.html("<i>n</i> / " + a + " = (" + k + " * <i>n</i>) >> " + m + "; for all <i>n</i> < " + m2);
});
$generate.click();