BigDecimal(String) vs. BigDecimal(double) [Floating-point arithmetics]

S

Stanimir Stamenkov

I've observed depending on whether a BigDecimal is constructed with
a String or double representing the same value, I get different
results in a rounding operation:

import java.math.BigDecimal;
import java.math.RoundingMode;
public class FPTest {
public static void main(String[] args) {
double a = 3.1231215;
BigDecimal b = new BigDecimal(a);
BigDecimal c = new BigDecimal(Double.toString(a));
System.out.println(b.setScale(6, RoundingMode.HALF_UP));
System.out.println(c.setScale(6, RoundingMode.HALF_UP));
}
}

The output I get is:

3.123121
3.123122

How are the two constructors BigDecimal(String) and
BigDecimal(double) different?
 
S

Stefan Ram

Stanimir Stamenkov said:
How are the two constructors BigDecimal(String) and
BigDecimal(double) different?

Decimal fractions often are not represented precisely by
double, and java.lang.Double#toString(double) will often not
create the exact decimal representation of the binary fraction
corresponding to the double value.

So, the decimal fraction given by the numeral in the source
code is possibly being distorted twice when it is represented
by a double and then converted to a string, but only once when
it is represented as a double.
 
P

Patricia Shanahan

Stanimir said:
I've observed depending on whether a BigDecimal is constructed with a
String or double representing the same value, I get different results in
a rounding operation:

import java.math.BigDecimal;
import java.math.RoundingMode;
public class FPTest {
public static void main(String[] args) {
double a = 3.1231215;
BigDecimal b = new BigDecimal(a);
BigDecimal c = new BigDecimal(Double.toString(a));
System.out.println(b.setScale(6, RoundingMode.HALF_UP));
System.out.println(c.setScale(6, RoundingMode.HALF_UP));
}
}

The output I get is:

3.123121
3.123122

How are the two constructors BigDecimal(String) and BigDecimal(double)
different?

The issue is that 3.1231215 is not exactly representable as a double.

Double.toString(x) does not return the exact String representation of
x's value. It returns the shortest String that would round to x's value
on conversion to double. As a result, c could be exactly 3.1231215.

On the other hand, b is forced to have a value that is exactly
representable as a double, and therefore cannot be exactly 3.1231215.
From the results, it appears to be slightly less. You could check all
this by printing the values of b and c without prior rounding.

new BigDecimal("3.1231215") would be certain to produce a BigDecimal
with exactly the specified value. Generally, if you want the exact
decimal handling of BigDecimal, it is a mistake to ever let a value be
converted to double.

Patricia
 
A

Arne Vajhøj

Stanimir said:
I've observed depending on whether a BigDecimal is constructed with a
String or double representing the same value, I get different results in
a rounding operation:

import java.math.BigDecimal;
import java.math.RoundingMode;
public class FPTest {
public static void main(String[] args) {
double a = 3.1231215;
BigDecimal b = new BigDecimal(a);
BigDecimal c = new BigDecimal(Double.toString(a));
System.out.println(b.setScale(6, RoundingMode.HALF_UP));
System.out.println(c.setScale(6, RoundingMode.HALF_UP));
}
}

The output I get is:

3.123121
3.123122

How are the two constructors BigDecimal(String) and BigDecimal(double)
different?

Read:

http://java.sun.com/javase/6/docs/api/java/math/BigDecimal.html#BigDecimal(double)

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top