ArithmeticException thrown during BigDecimal.divide

后端 未结 9 668
渐次进展
渐次进展 2020-11-30 08:41

I thought java.math.BigDecimal is supposed to be The Answer™ to the need of performing infinite precision arithmetic with decimal numbers.

Consider the followi

相关标签:
9条回答
  • 2020-11-30 08:54

    Notice we are using a computer... A computer has a lot of ram and precision takes ram. So when you want an infinite precision you need
    (infinite * infinite) ^ (infinite * Integer.MAX_VALUE) terrabyte ram...

    I know 1 / 3 is 0.333333... and it should be possible to store it in ram like "one divided by three" and then you can multiply it back and you should have 1. But I don't think Java has something like that...
    Maybe you have to win the Nobel Price for writing something doing that. ;-)

    0 讨论(0)
  • 2020-11-30 08:56

    The class is BigDecimal not BigFractional. From some of your comments it sounds like you just want to complain that someone didn't build in all possible number handling algorithms into this class. Financial apps do not need infinite decimal precision; just perfectly accurate values to the precision required (typically 0, 2, 4, or 5 decimal digits).

    Actually I have dealt with many financial applications that use double. I don't like it but that was the way they are written (not in Java either). When there are exchange rates and unit conversions then there are both the potential of rounding and bruising problems. BigDecimal eliminates the later but there is still the former for division.

    0 讨论(0)
  • 2020-11-30 09:01

    I accept that Java doesn't have great support for representing fractions, but you have to realise that it is impossible to keep things entirely precise when working with computers. At least in this case, the exception is telling you that precision is being lost.

    As far as I know, "infinite precision arithmetic with decimal numbers" just isn't going to happen. If you have to work with decimals, what you're doing is probably fine, just catch the exceptions. Otherwise, a quick google search finds some interesting resources for working with fractions in Java:

    http://commons.apache.org/math/userguide/fraction.html

    http://www.merriampark.com/fractions.htm

    Best way to represent a fraction in Java?

    0 讨论(0)
  • 2020-11-30 09:02

    By the way, I'd really appreciate insight from people who've worked with financial software. I often heard BigDecimal being advocated over double

    In financial reports we use alwasy BigDecimal with scale = 2 and ROUND_HALF_UP, since all printed values in a report must be lead to a reproducable result. If someone checks this using a simple calculator.

    In switzerland they round to 0.05 since they no longer have 1 or 2 Rappen coins.

    0 讨论(0)
  • 2020-11-30 09:06

    If this is not the right answer, what CAN we use for exact division in financial calculation? (I mean, I don't have a finance major, but they still use division, right???).

    Then I was in primary school1, they taught me that when you divide by 1 by 3 you get a 0.33333... i.e. a recurring decimal. Division of numbers represented in decimal form is NOT exact. In fact for any fixed base there will be fractions (the result of dividing one integer by another) that cannot be represented exactly as a finite precision floating point number in that base. (The number will have a recurring part ...)

    When you do financial calculations involving division, you have to consider the what to do with a recurring fraction. You can round it up, or down, or to the nearest whole number, or something else, but basically you cannot just forget about the issue.

    The BigDecimal javadoc says this:

    The BigDecimal class gives its user complete control over rounding behavior. If no rounding mode is specified and the exact result cannot be represented, an exception is thrown; otherwise, calculations can be carried out to a chosen precision and rounding mode by supplying an appropriate MathContext object to the operation.

    In other words, it is your responsibility to tell BigDecimal what to do about rounding.

    EDIT - in response to these followups from the OP.

    How does BigDecimal detect infinite recurring decimal?

    It does not explicitly detect the recurring decimal. It simply detects that the result of some operation cannot be represented exactly using the specified precision; e.g. too many digits are required after the decimal point for an exact representation.

    It must keep track of and detect a cycle in the dividend. It COULD HAVE chosen to handle this another way, by marking where the recurring portion is, etc.

    I suppose that BigDecimal could have been specified to represent a recurring decimal exactly; i.e. as a BigRational class. However, this would make the implementation more complicated and more expensive to use2. And since most people expect numbers to be displayed in decimal, and the problem of recurring decimal recurs at that point.

    The bottom line is that this extra complexity and runtime cost would be inappropriate for typical use-cases for BigDecimal. This includes financial calculations, where accounting conventions do not allow you to use recurring decimals.


    1 - It was an excellent primary school ...

    2 - Either you try to remove common factors of the divisor and dividend (computationally expensive), or allow them to grow without bounds (expensive in space usage ... and computationally for later operations).

    0 讨论(0)
  • 2020-11-30 09:15

    To divide save, you have to set the MATHcontext,

    BigDecimal bd = new BigDecimal(12.12, MathContext.DECIMAL32).divide(new BigDecimal(2)).setScale(2, RoundingMode.HALF_UP);

    0 讨论(0)
提交回复
热议问题