patternjavaMinor
Saturated arithmetic
Viewed 0 times
saturatedarithmeticstackoverflow
Problem
For project Euler, I need quite often to test things like is
As usual, feel free to ignore my slightly deviating coding conventions. The code has been optimized, so it's a bit hacky. There should be no bugs as it's thoroughly tested. Simplifications and optimizations are most welcome.
xyz < 1e18. Since BigInteger is usually too slow, long overflows, and double may return incorrect result due to rounding, I wanted to use long with appropriate checks. As Guava's LongMath.checkedMultiply throws, it can't be used as exception handling is too slow, too. So I decided to write a saturated arithmetic class.As usual, feel free to ignore my slightly deviating coding conventions. The code has been optimized, so it's a bit hacky. There should be no bugs as it's thoroughly tested. Simplifications and optimizations are most welcome.
@UtilityClass public class SaturatedMath {
public static long pow(long base, int exp) {
if (exp==0) return 1;
checkArgument(exp>=0);
// Handle small bases and also Long.MIN_VALUE
if (Math.abs(base) = FLOOR_ROOTS_MAX_LONG.length) return saturate(base +limit) return Long.MAX_VALUE;
if (base =63 ? saturate(sign) : sign =63 ? Long.MAX_VALUE : 1L 0; exp>>=1) {
if ((exp&1) != 0) result *= x;
x *= x;
}
return result;
}
public static long mul(long x, long y) {
final long result = x * y;
// See https://goo.gl/ZMEZEa
final int nlz = Long.numberOfLeadingZeros(x) + Long.numberOfLeadingZeros(~x)
+ Long.numberOfLeadingZeros(y) + Long.numberOfLeadingZeros(~y);
if (nlz > 65) return result;
if (nlz +FLOOR_SQRT_MAX_LONG) return Long.MAX_VALUE;
if (x +FLOOR_CBRT_MAX_LONG) return Long.MAX_VALUE;
if (x =3, the n-th item is the n-th root of Long.MAX_VALUE.
// The first three values are unused.
private static final int[] FLOOR_ROOTS_MAX_LONG = {
0, 0, 0, 2097151, 55108, 6208, 1448, 511,
234, 127, 78, 52, 38, 28, 22, 18,
15, 13, 11, 9, 8, 7, 7, 6,
6, 5, 5, 5, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3,
// The next value would be 2, so we stop here.
};
}Solution
It looks good to me, except for a couple of things:
Is there a particular reason you did
How is it special? Explain in the method name or a Javadoc comment (
Anyway, aside from that (and the things you mention in your coding style page thingamabobber) it looks good! Nicely done.
private static long saturate(boolean negative) {
return negative ? Long.MIN_VALUE : Long.MAX_VALUE;
}Is there a particular reason you did
negative instead of positive? It feels like an arbitrary choice to me. If it's not, add a brief comment explaining why. If it is, the convention (well, that I've seen, which means that it might well be the opposite) is to have true mean positive, not negative.private static long powSpecial(long base, int exp) {How is it special? Explain in the method name or a Javadoc comment (
/** */). Here, it seems like it's for small numbers, so a better method name would be powSmallBases. It may only be used here, but it's rather convenient to be able to read your own code later, if you want to change it later.Anyway, aside from that (and the things you mention in your coding style page thingamabobber) it looks good! Nicely done.
Code Snippets
private static long saturate(boolean negative) {
return negative ? Long.MIN_VALUE : Long.MAX_VALUE;
}private static long powSpecial(long base, int exp) {Context
StackExchange Code Review Q#92686, answer score: 4
Revisions (0)
No revisions yet.