5

I am trying to make a BigDecimal from a string. Don't ask me why, I just need it! This is my code:

Double theDouble = new Double(".3");
System.out.println("The Double: " + theDouble.toString());
BigDecimal theBigDecimal = new BigDecimal(theDouble);
System.out.println("The Big: " + theBigDecimal.toString());

This is the output I get?

The Double: 0.3
The Big: 0.299999999999999988897769753748434595763683319091796875

Any ideas?

Diego
  • 16,830
  • 8
  • 34
  • 46

4 Answers4

12

When you create a double, the value 0.3 cannot be represented exactly. You can create a BigDecimal from a string without the intermediate double, as in

new BigDecimal("0.3")

A floating point number is represented as a binary fraction and an exponent. Therefore there are some number that cannot be represented exactly. There is an analogous problem in base 10 with numbers like 1/3, which is 0.333333333..... Any decimal representation of 1/3 is inexact. This happens to a DIFFERENT set of fractions in binary, and 0.3 is one of the set that is inexact in binary.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
  • Why cant it be represented exactly as a double? – Diego Sep 11 '10 at 23:06
  • 2
    @Diego: This is, if not the most common question on SO, at least in the top five. It takes a little time to understand, though. Read [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.sun.com/source/806-3568/ncg_goldberg.html) – Michael Petrotta Sep 11 '10 at 23:08
  • Heck, you supplied the canonical answer to this question and is the duplicate you should have used to close the recent [similar question](https://stackoverflow.com/questions/45663315/multiply-two-numbers-precisely-in-java). – Hovercraft Full Of Eels Aug 13 '17 at 18:08
  • @HovercraftFullOfEels I've lost track of which "canonical" answers I've written. This was almost 7 years ago :-) – Jim Garrison Aug 13 '17 at 18:25
  • Well it has well stood the test of time. – Hovercraft Full Of Eels Aug 13 '17 at 18:27
1

Another way is to use MathContext.DECIMAL32 which guarantees 7 digit precision (which is good enough in our case):

Double theDouble = new Double(".3");
System.out.println("The Double: " + theDouble.toString());
BigDecimal theBigDecimal = new BigDecimal(theDouble, MathContext.DECIMAL32);  // <-- here
System.out.println("The Big: " + theBigDecimal.toString());

OUTPUT

The Double: 0.3
The Big: 0.3000000
Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
1

Since new Double(".3") can't be represented exactly, the nearest value is 0x1.3333333333333P-2 or .299999999999999988897769753748434595763683319091796875, what would be need to is this:

Double theDouble = new Double(".3");
System.out.println("The Double: " + theDouble.toString());
BigDecimal theBigDecimal = new 
BigDecimal(theDouble).setScale(2, RoundingMode.CEILING);  // <-- here
System.out.println("The Big: " + theBigDecimal.toString());

This will print:

The Double: 0.3
The Big: 0.30
0

You can give a big decimal a specified precision. e.g. append to your example:

Double theDouble = new Double(".3");
theBigDecimal = new BigDecimal(theDouble, new MathContext(2));
System.out.println("The Big: " + theBigDecimal.toString());

This will print out "0.30"

Steve B.
  • 55,454
  • 12
  • 93
  • 132
  • Thanks, but I dont always know that the precision would be. The string I am actually reading from a file. – Diego Sep 11 '10 at 23:18