4

what is the best way to to get the closest, non-smaller number that is divisible by 16?

the method I came up with doesn't look very elegant or fast

int non_smaller_int_divisible_by_16(int x)
{
  return x + ((16 - (x % 16)) % 16);
}

the expected results are

result | X values
-------|----------
16     | 1,2,..., 16
32     | 17, 18, ... 32
48     | 33, 34, ..., 48

etc

John Carter
  • 53,924
  • 26
  • 111
  • 144
Aviad Rozenhek
  • 2,259
  • 3
  • 21
  • 42

4 Answers4

11
int non_smaller_int_divisible_by_16(int x)
{
  return (x + 15) & ~15;
}

Since 16 is a power of two, you can use binary masking - add 15 so we get the next highest multiple, and mask with the bitwise inverse of 15, to clear the bottom bits.

Edit:

It's not clear what you want to happen with negative numbers - both your and my code will round to more-positive values (ie negative numbers will get smaller). If negative values don't make sense in your program, it'd be better to use an unsigned type.

Finally, you might be interested to look at Bit Twiddling Hacks, which is a great collection of some really clever (if often extremely obscure) tricks along these lines.

John Carter
  • 53,924
  • 26
  • 111
  • 144
  • indeed, negative numbers are irrelevant here, and with unsigned types the modulo operator works just like in college math, making the function much simpler. – Aviad Rozenhek Jun 06 '11 at 10:08
5

@therefromhere's solution is more elegant and faster, but if you need to do this with a number that isn't a power of 2 then you can use this approach.

int non_smaller_int_divisible_by_n(int x, int n)
{
  return n*((x+n-1)/n);
}
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 3
    Actually, if you declare everything "unsigned" and make n a compile-time constant, GCC (at least) produces identical code to the bit-twiddling version. Since your form is both clearer and more general, it is preferable... – Nemo Jun 05 '11 at 18:45
  • @nemo you are very correct, in fact I am promoting this to be the new answer – Aviad Rozenhek Jun 06 '11 at 09:58
1

following @nemo's comment, there's a nifty way to solve this that works for all mod bases, is very readable, and should be fast

unsigned int non_smaller_int_divisible_by_16(unsigned int x)
{
   return x + ((-x) % 16);
}

the generic version is therefore

unsigned int non_smaller_int_divisible_by_base(unsigned int x, unsigned int base)
{
   return x + ((-x) % base);
}
Aviad Rozenhek
  • 2,259
  • 3
  • 21
  • 42
-1
int non_smaller_int_divisible_by_16(int x) {
    return (x & 15) ? (x | 15) + 1 : x;
}
Santiago Alessandri
  • 6,630
  • 30
  • 46