tags:

views:

311

answers:

4

How can you divide a number n for example by 24 using shifting operators and additions?

(n % 24 == 0)

A: 

While there is no doubt a clever hack for 24, using shift operators [and/or subtractions] only really makes sense for powers of 2. Even then, its far more likely to confuse readers than it is to generate more efficient code with a modern compiler.

Ruben Bartelink
Oh... Do you think the question was about a *clever* way? Well that changes everything... :)
Pascal Cuoq
@Pascal: Without the explanation, it all sounds very homeworky. Nice answer by you, +1
Ruben Bartelink
+4  A: 

The pencil-and-paper algorithm for the division uses only "shifts" (base 10 shifts) and subtractions. You can do exactly the same thing in base 2.

Sorry I can't find a link for the algorithm, but you should have learnt it as a child.

EDIT: actually since additions are cheap, you don't have to try to extract the correct digits one by one, so you can simplify the algorithm a bit...

Assuming positive dividend and divisor...

Take the power of two immediately larger than the divisor (here, 32).

It is easy to divide your number by this power of two. Say the division produces k1. Subtract k1*24 from the number (call the rest r1) and iterate...

When you have obtained k1, k2, ... kn numbers and the rest rn no longer contains 32, do a last check to see if rn contains 24.

The result of the division is k1+k2+...+kn (+1 if 24 fits in rn).

Pascal Cuoq
Note that this algorithm handle gracefully the special case where you are dividing by a power of two: in this case it converges in one step. It can take a logarithmic number of subtractions/additions if the divisor is a power of two plus one.
Pascal Cuoq
I'm not sure I understand your answer.. what changes in each iteration? I tried `150/32 = 4;` `150-32*4 = 22` which is < 24; but the desired result is 6.
int3
240/32 = 7; 240-32*7=16 which is < 24. desired result is 10. doesn't seem to work.
Etan
@int3, Etan: In order to be a simplified version of the pencil-and-paper algorithm, the "k1*32" should of course be read "k1*24". I edited the answer to fix it.
Pascal Cuoq
The reason it works is that k1, .., kn are all the times 24 has been removed from the dividend before arriving to a rest that didn't contain 24.
Pascal Cuoq
+1  A: 
int
div24(int value) {
   int result = 0;
   while (value >= 24) {       
      int accum = 24;
      int tmp = 1;   
      while (accum + accum <= value) {
         accum += accum;
      tmp += tmp;
      }
      value -= accum;   
      result += tmp;
   }   
   return result;
}
Andreas Brinck
Using two loops? You're testing repeatedly to find the highest value of tmp such that `(24 << tmp) < value` but every time you find such a factor, you restart `tmp` at 1.
MSalters
sorry, you're algorithm is of course faster, this was the first thing that came to my mind.
Andreas Brinck
+2  A: 

This works by first finding the highest bit of the result, and then working back.

int div24(int value) {
  // Find the smallest value of n such that (24<<n) > value
  int tmp = 24;
  for (int n = 0; tmp < value; ++n)
    tmp <<= 1;
  // Now start working backwards to find bits of the result. This is O(i).
  int result = 0;
  while(value != 0) {
    tmp >>= 1;
    result <<= 1;
    if (value > tmp) { // Found one bit.
       value -= tmp; // Subtract (24<<i)
       result++;
    }
  }
  return result;
}

Example:

Value = 120 :  n = 2
Step 0: tmp = 96, result = 0, value = 24, result = 1
Step 1: tmp = 48, result = 2
Step 2: tmp = 24, result = 4, value = 0, result = 5
MSalters