Find nearest multiple of 8 from a variable?

Hi,

i want a sketch that would return the nearest multiple of 8 (rounded up always) from a variable, for example.

X = 4, returns 8
X=1, returns 8
X=8, returns 8
etc...

X=11, returns 16
X=14, returns 16
etc...

X=20, returns 24
X=17, returns 24
etc

  • divide by 8
  • add one to the result
  • multiply that by 8 again

How so?

Say X = 4,

4/8 = 0.5

0.5 + 1 = 1.5

1.5*8 = 12 (Should be 8 ).

edit: Whoops, i dont know what im on about here, should be 8

Something like
x = (x + 7) & ~7 ?

4/8 = 0.5

No. 4/8 = 0

4.0/8.0 = 0.5. Not the same thing at all.

adilmalik:
How so?

Say X = 4,

4/8 = 0.5

0.5 + 1 = 1.5

1.5*8 = 12 (Should be 16).

x = 4
4 / 8 = 0
0 + 1 = 1
1 * 8 = 8

Oh i see, Thankyou!, ive come up with this, dont have an arduino at hand to test it, what do you guys think:

X = 8 * ceil((X / 8))

I think ceil() takes a float argument, so if x is an int then use ceil(x/8.0), because ceil(x/8) will always round down

if x is an int, I believe the modulus operator is faster than a float division

if(!(x%8))answer=x;
else answer=x-(x%8)+1;

or the shorthand version

answer=(x%8)?x-(x%8)+1:x;

or ... (I think)

answer = ((x >> 3) + 1) << 3);

...R

Robin2:
or ... (I think)

answer = ((x >> 3) + 1) << 3);

...R

try x== 0

I had the same thought :wink:
the addition of 1 should be conditional something like

answer = ((x >> 3) + ((x&7)>0) << 3);

//assumes true == 1 and false == 0

x = (x + (n-1)) & ~(n-1);

this only works for powers of two, due to the sexy nature of how bit masking works - in all other cases - you do this:

x = ((x + (n-1)) / n) * n);  // edited

so, to answer the fundamental question here - AWOL was spot on here with the solution, unfortunately since it was low level bitwise C it seems that many have failed to understand what was actually going on.

x = (x + 7) & ~7;
x = ((x + 7) / 8) * 8); // edited

do exactly the same thing.. push x over the 8 boundary (but, only by 7) and then divide ..

x = (x + 7) & ~7;

x = (x + 7) / 8;




do exactly the same thing

No, they don't.
The first one is correct (for positive integers). The second one isn't even close.

Pete

el_supremo:
No, they don't.
The first one is correct (for positive integers). The second one isn't even close.

woops :slight_smile: forgot the multiply - need more coffee.

x = ((x + 7) / 8) * 8;

i would have used the first method (as reported by AWOL) anyhow :stuck_out_tongue:

Heh - I'm just downing a cup of tea and a chocolate bar.
Yup - AWOL's solution is definitely the way to it.

Pete

robtillaart:
try x== 0

the addition of 1 should be conditional something like

I admit I had not thought of that.
But we don't expect division by 0 to work so we check for it before we try the division - same here. perhaps?
Rather than make the formula more complex?

...R

x = 0;
x = (x + 7) & ~7;

gives the result of x = 0 - there is no need to have a conditional for it.

ardiri:

x = 0;

x = (x + 7) & ~7;




gives the result of x = 0 - there is no need to have a conditional for it.

I think it works, but would you care to explain the maths?

...R

Robin2:
I think it works, but would you care to explain the maths?

we know it works :slight_smile:

are you familiar with binary (0's and 1's) and how integers are stored internally?

anyhow, here is the catch - since it is a multiple of a power of 2, we can use the magic trickery of bit wise operations. & ~7 really means - remove the lower three bits from the number (7 = 111 in binary, ~7 = 111111...111111000 in binary) - which really means make them 0. so if you have a number like 181 it is in binary as: 10110101 making the last three bits 0 would make the number: 10110000 which would be the number 176. you can read up more at:

Bitwise operation - Wikipedia <-- better explanation

as i mentioned earlier, when the number (n) isn't a power of 2, you need to use another formula:

x = ((x + (n-1)) / n) * n);

as the bit masking technique wont work then.

ardiri:
we know it works :slight_smile:

are you familiar with binary (0's and 1's) and how integers are stored internally?

I had figured out the stuff in your post. What I am interested to understand is why it works as maths rather than just as bit manipulations. The bit manipulation stuff is HOW not WHY.

...R