Skip to main content
3 of 6
added 241 characters in body
maaartinus
  • 13.7k
  • 1
  • 36
  • 75

I guess, a really fast solution on a modern CPU looks like this:

int mask = 0x2AAAAAAA; // special handling for the sign bit
int diff = 2 * Integer.bitCount(x & mask) + Integer.bitCount(x & ~mask);

Don't be fooled by the complicated code behind it, it's an intristic and translates to a single cycle instruction.

Now we have a number between 0 and 30, which is divisible by 3 iff x is divisible by 3. The fastest way is probably a table packed into a single int.

 return (TABLE << diff) < 0;

#EDIT

I've change the above code slightly to make the explanation simpler.

The remainder modulo 3 is the same for 1 and 10, as 10 % 3 = 1, which means that in decimal the position of a digit doesn't matter for this remainder. This leads to the well-known digit sum rule.

In binary, it doesn't work exactly like this as 2 % 3 != 1. But 4 % 3 = 1, so we can rewrite (8a + 4b + 2c + d) % 3 = (2(a+c) + (b+d)) % 3. Since every digit is either zero or one, all we need is to count the ones in the appropriate positions. As the weight of the highest bit is -2**31, it needs a special handling (see the mask).

#EDIT

I see I missed a trivial optimization. This is the whole code afterwards:

private static final int TABLE = ....;

int diff = Integer.bitCount(x & 0x2AAAAAAA) + Integer.bitCount(x);
return (TABLE << diff) < 0;
maaartinus
  • 13.7k
  • 1
  • 36
  • 75