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

Discussion in 'Java' started by Stanimir Stamenkov, Jul 17, 2008.

1. ### Stanimir StamenkovGuest

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?

--
Stanimir
Stanimir Stamenkov, Jul 17, 2008

2. ### Stefan RamGuest

Stanimir Stamenkov <> writes:
>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.
Stefan Ram, Jul 17, 2008

3. ### Patricia ShanahanGuest

Stanimir Stamenkov wrote:
> 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
Patricia Shanahan, Jul 17, 2008
4. ### Arne VajhøjGuest

Stanimir Stamenkov wrote:
> 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?

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

Arne
Arne Vajhøj, Jul 18, 2008
5. ### Stanimir StamenkovGuest

Thu, 17 Jul 2008 19:34:58 -0400, /Arne Vajhøj/:
> Stanimir Stamenkov wrote:
>
>> How are the two constructors BigDecimal(String) and BigDecimal(double)
>> different?

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

Thank you, Arne, Patricia and Stefan for your replies. I now feel
much confident in what's going on. May be the detail I've been
missing mainly is the Double.toString(double) conversion.

--
Stanimir
Stanimir Stamenkov, Jul 18, 2008