views:

702

answers:

5

Hello

is there a fast algorithm, similar to power of 2, which can be used with 3, i.e. n%3. Perhaps something that uses the fact that if sum of digits is divisible by three, then the number is also divisible.

This leads to a next question. What is the fast way to add digits in a number? I.e. 37 -> 3 +7 -> 10 I am looking for something that does not have conditionals as those tend to inhibit vectorization

thanks

A: 

I'm not sure what the performance would be like, but for your second question you could convert the number to a string, iterate the string and add ( - 48) to get the int value.

Myles
+1  A: 

Not sure for your first question, but for your second, you can take advantage of the % operator and integer division:

int num = 12345;
int sum = 0;
while (num) {
    sum += num % 10;
    num /= 10;
}

This works because 12345 % 10 = 5, 12345 / 10 = 1234 and keep going until num == 0

Austin Hyde
+1 Nice #2. solution.
Kyle Rozendo
yes, it is that obvious solution.However division and modulo a very expensive operations, on the order of hundred of cycles on my platform.I am more interested in something that does not involve those.I have to say that this is a purely curiosity question.
aaa
+10  A: 

4 % 3 == 1, so (4^k * a + b) % 3 == (a + b) % 3. You can use this fact to evaluate x%3 for a 32-bit x:

x = (x >> 16) + (x & 0xffff);
x = (x >> 10) + (x & 0x3ff);
x = (x >> 6) + (x & 0x3f);
x = (x >> 4) + (x & 0xf);
x = (x >> 2) + (x & 0x3);
x = (x >> 2) + (x & 0x3);
x = (x >> 2) + (x & 0x3);
if (x == 3) x = 0;

(Untested - you might need a few more reductions.) Is this faster than your hardware can do x%3? If it is, it probably isn't by much.

Keith Randall
+3  A: 

This comp.compilers item has a specific recommendation for computing modulo 3.

An alternative, especially if the maximium size of the dividend is modest, is to multiply by the reciprocal of 3 as a fixed-point value, with enough bits of precision to handle the maximum size dividend to compute the quotient, and then subtract 3*quotient from the the dividend to get the remainder. All of these multiplies can be implemented with a fixed sequence of shifts-and-adds. The number of instructions will depend on the bit pattern of the reciprocal. This works pretty well when the dividend max is modest in size.

Regarding adding digits in the number... if you want to add the decimal digits, you're going to end up doing what amounts to a number-conversion-to-decimal, which involves divide by 10 somewhere. If you're willing to settle for adding up the digits in base2, you can do this with an easy shift-right and add loop. Various clever tricks can be used to do this in chunks of N bits to speed it up further.

Ira Baxter
A: 

thanks guys

Mr. Baxters Link to compiler newsgroup has a few algorithms which are useful for me

aaa