Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bit Hack - Round off to multiple of 8

can anyone please explain how this works (asz + 7) & ~7; It rounds off asz to the next higher multiple of 8.

It is easy to see that ~7 produces 11111000 (8bit representation) and hence switches off the last 3 bits ,thus any number which is produced is a multiple of 8.

My question is how does adding asz to 7 before masking [edit] produce the next higher[end edit] multiple of 8 ? I tried writing it down on paper

like :

1 + 7 = 8  = 1|000 (& ~7) -> 1000
2 + 7 = 9  = 1|001 (& ~7) -> 1000
3 + 7 = 10 = 1|010 (& ~7) -> 1000
4 + 7 = 11 = 1|011 (& ~7) -> 1000
5 + 7 = 12 = 1|100 (& ~7) -> 1000
6 + 7 = 13 = 1|101 (& ~7) -> 1000
7 + 7 = 14 = 1|110 (& ~7) -> 1000
8 + 7 = 15 = 1|111 (& ~7) -> 1000

A pattern clearly seems to emerge which has been exploited .Can anyone please help me it out ?

Thank You all for the answers.It helped confirm what I was thinking. I continued the writing the pattern above and when I crossed 10 , i could clearly see that the nos are promoted to the next "block of 8" if I can say so.

Thanks again.

like image 807
user212721 Avatar asked Nov 19 '09 21:11

user212721


2 Answers

It's actually adding 7 to the number and rounding down.

This has the desired effect of rounding up to the next multiple of 8. (Adding +8 instead of +7 would bump a value of 8 to 16.)

like image 52
Broam Avatar answered Oct 17 '22 06:10

Broam


Well, if you were trying to round down, you wouldn't need the addition. Just doing the masking step would clear out the bottom bits and you'd get rounded to the next lower multiple.

If you want to round up, first you have to add enough to "get past" the next multiple of 8. Then the same masking step takes you back down to the multiple of 8. The reason you choose 7 is that it's the only number guaranteed to be "big enough" to get you from any number up past the next multiple of 8 without going up an extra multiple if your original number were already a multiple of 8.

In general, to round up to a power of two:

unsigned int roundTo(unsigned int value, unsigned int roundTo)
{
    return (value + (roundTo - 1)) & ~(roundTo - 1);
}
like image 43
Carl Norum Avatar answered Oct 17 '22 06:10

Carl Norum