'fixed point arithmetics in java with fast performance
I need to represent some numbers in Java with perfect precision and fixed number of decimal points after decimal point; after that decimal point, I don't care. (More concretely - money and percentages.)
I used Java's own BigDecimal now, but I found out, that it's really slow and it starts to show in my application.
So I want to solve it with a "regular" integers and a fixed-point arithmetics (long integers have big enough precision for my purposes).
Now, I would think that I am not the first one who has this kind of problem and there would be already a library for that, that already has multiplication/division implemented - but it seems that it isn't.
Now, I very probably can write it myself (and I probably will), but really, am I really the first person that needs this? Isn't there already some library for that?
Solution 1:[1]
decimal4j is a Java library for fast fixed precision arithmetic based on longs with support for up to 18 decimal places.
Disclosure: I am involved in the decimal4j project.
Solution 2:[2]
Although this is not exactly what you are asking about, this can speed up your app without leaving BigDecimal:
Since Java 8, this is solved by BigDecimal itself. A new class MathContext was added and limits the precision to which the operations are calculated.
var num = new BigDecimal("1234.56780", new MathContext(10, RoundingMode.DOWN));
The catch is that the precision 10 does not apply to digits after decimal point. It applies to the number of significant digits. For 1234.50, 6 is needed.
For 1_500_000_000.100, 13 is needed to keep the number as is.
So the precision might suffer when you had a precision of 10 and counted billions of Czech Korunas.
Still, a precision of, say, 1000, is way faster than unlimited precision (which is I think the default).
This can also be applied to the individual operations:
BigDecimal n = new BigDecimal("0.12345");
n = n.pow(2, new MathContext(1000, RoundingMode.DOWN));
n = n.pow(2, new MathContext(1000, RoundingMode.DOWN));
n = n.pow(2, new MathContext(1000, RoundingMode.DOWN));
n = n.pow(2, new MathContext(1000, RoundingMode.DOWN));
Solution 3:[3]
Not sure why you need a library for it.
For example, say you want to add two longs with the same fixed precision
long c = a + b;
Say you have a fixed precision number you want to multiple by an integer
long c = a * i;
Say you want to divide a number by a integer rounding to zero
long c = a / i;
Say you want to print a fixed precision number with 3 decimal places.
System.out.println(c / 1e3);
Perhaps you are over thinking the problem and assuming you need a library for everything.
If you are using long or double you might want a small number helper methods for rounding, but you don't need a library as such.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | Peter Lawrey |
