JDK-8197995 : Insufficient BigDecimal and BigInteger Defaulting Behaviour
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.math
  • Affected Version: 8,9,10
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • Submitted: 2018-02-15
  • Updated: 2022-03-15
  • Resolved: 2018-02-15
Related Reports
Relates :  
Description
A DESCRIPTION OF THE REQUEST :
BigDecimal and BigInteger arithmetic does not default to decimal, non-floating point arithmetic mode.

BigDecimal a = new BigDecimal(0.1);
     
BigDecimal b = new BigDecimal(0.1);
     
BigDecimal x = a.multiply(b);
     
out.println(x.stripTrailingZeros().toPlainString());


JUSTIFICATION :
In order for this to produce the anticipated behaviour,
there must be a MathContext object submitted, scale
values set for a and b (or rounding performed on the multiply call), 
none of which should be necessary in this example.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Should print an answer of 

0.01

with no further configuration.
ACTUAL -
Instead prints out a floating point default result of

0.01000000000000000111022302462515657123851077828659396139564708135883709660962637144621112383902072906494140625

---------- BEGIN SOURCE ----------
import java.math.RoundingMode;
import java.math.MathContext;
import java.math.BigDecimal;
import static java.lang.System.out;

public class ArbitraryNumbers 
{
public static void main(String ... args)
{
BigDecimal a = new BigDecimal(0.1);
     
BigDecimal b = new BigDecimal(0.1);
     
BigDecimal x = a.multiply(b);
     
out.println(x.stripTrailingZeros().toPlainString());
}
}
---------- END SOURCE ----------


Comments
The desired behavior can be had by following the advice given in the spec for the BigDecimal(double) constructor: " The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding. The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one. " In brief, using the string-based constructor since 0.1 is not exactly representable as a binary double value. Closing as not a bug.
15-02-2018