I use the following function to calculate log base 2 for integers:
public static int log2(int n){
if(n <= 0) throw new IllegalArgumentException();
return 31 - Integer.numberOfLeadingZeros(n);
}
Does it have optimal performance?
Does someone know ready J2SE API function for that purpose?
UPD1 Surprisingly for me, float point arithmetics appears to be faster than integer arithmetics.
UPD2 Due to comments I will conduct more detailed investigation.
UPD3 My integer arithmetic function is 10 times faster than Math.log(n)/Math.log(2).
If you are thinking about using floating-point to help with integer arithmetics, you have to be careful.
I usually try to avoid FP calculations whenever possible.
Floating-point operations are not exact. You can never know for sure what will
(int)(Math.log(65536)/Math.log(2))evaluate to. For example,Math.ceil(Math.log(1<<29) / Math.log(2))is 30 on my PC where mathematically it should be exactly 29. I didn’t find a value for x where(int)(Math.log(x)/Math.log(2))fails (just because there are only 32 “dangerous” values), but it does not mean that it will work the same way on any PC.The usual trick here is using “epsilon” when rounding. Like
(int)(Math.log(x)/Math.log(2)+1e-10)should never fail. The choice of this “epsilon” is not a trivial task.More demonstration, using a more general task – trying to implement
int log(int x, int base):The testing code:
If we use the most straight-forward implementation of logarithm,
this prints:
To completely get rid of errors I had to add epsilon which is between 1e-11 and 1e-14.
Could you have told this before testing?
I definitely could not.