fixed point arithmetics in java with fast performance

前端 未结 4 1818
盖世英雄少女心
盖世英雄少女心 2020-12-17 01:42

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 concre

相关标签:
4条回答
  • 2020-12-17 02:18

    Are you completely sure BigDecimal is the performance problem? Did you use a profiler to find out? If yes, two options that could help are:

    1) Use long and multiply all values by a factor (for example 100 if you are interested in cents).

    2) Use a specially designed class that implements something similar to BigDecimal, but using long internally. I don't know if a good open source library exists (maybe the Java Math Fixed Point Library?). I wrote one such class myself quite a long time ago (2001 I believe) for J2ME. It's a bit tricky to get right. Please note BigDecimal uses a long internally as well except if high precision is needed, so this solution will only help a tiny bit in most cases.

    Using double isn't a good option in many cases, because of rounding and precision problems.

    0 讨论(0)
  • 2020-12-17 02:22

    decimal4j is a Java library for fast fixed precision arithmetic based on longs with support for up to 18 decimal places.

    Disclaimer: I am involved in the decimal4j project.

    0 讨论(0)
  • 2020-12-17 02:29

    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.

    0 讨论(0)
  • 2020-12-17 02:40

    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));
    
    0 讨论(0)
提交回复
热议问题