[java] Convert double to BigDecimal and set BigDecimal Precision

In Java, I want to take a double value and convert it to a BigDecimal and print out its String value to a certain precision.

import java.math.BigDecimal;
public class Main {
    public static void main(String[] args) {
        double d=-.00012;
        System.out.println(d+""); //This prints -1.2E-4

        double c=47.48000;
        BigDecimal b = new BigDecimal(c);
        System.out.println(b.toString()); 
        //This prints 47.47999999999999687361196265555918216705322265625 
    }
}

It prints this huge thing:

47.47999999999999687361196265555918216705322265625

and not

47.48

The reason I'm doing the BigDecimal conversion is sometimes the double value will contain a lot of decimal places (i.e. -.000012) and the when converting the double to a String will produce scientific notation -1.2E-4. I want to store the String value in non-scientific notation.

I want to have BigDecimal always have two units of precision like this: "47.48". Can BigDecimal restrict precision on conversion to string?

This question is related to java double bigdecimal

The answer is


You want to try String.format("%f", d), which will print your double in decimal notation. Don't use BigDecimal at all.

Regarding the precision issue: You are first storing 47.48 in the double c, then making a new BigDecimal from that double. The loss of precision is in assigning to c. You could do

BigDecimal b = new BigDecimal("47.48")

to avoid losing any precision.


The reason of such behaviour is that the string that is printed is the exact value - probably not what you expected, but that's the real value stored in memory - it's just a limitation of floating point representation.

According to javadoc, BigDecimal(double val) constructor behaviour can be unexpected if you don't take into consideration this limitation:

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.

So in your case, instead of using

double val = 77.48;
new BigDecimal(val);

use

BigDecimal.valueOf(val);

Value that is returned by BigDecimal.valueOf is equal to that resulting from invocation of Double.toString(double).


BigDecimal b = new BigDecimal(c).setScale(2,BigDecimal.ROUND_HALF_UP);

The String.format syntax helps us convert doubles and BigDecimals to strings of whatever precision.

This java code:

double dennis = 0.00000008880000d;
System.out.println(dennis);
System.out.println(String.format("%.7f", dennis));
System.out.println(String.format("%.9f", new BigDecimal(dennis)));
System.out.println(String.format("%.19f", new BigDecimal(dennis)));

Prints:

8.88E-8
0.0000001
0.000000089
0.0000000888000000000

In Java 9 the following is deprecated:

BigDecimal.valueOf(d).setScale(2, BigDecimal.ROUND_HALF_UP);

instead use:

BigDecimal.valueOf(d).setScale(2, RoundingMode.HALF_UP);

Example:

    double d = 47.48111;

    System.out.println(BigDecimal.valueOf(d)); //Prints: 47.48111

    BigDecimal bigDecimal = BigDecimal.valueOf(d).setScale(2, RoundingMode.HALF_UP);
    System.out.println(bigDecimal); //Prints: 47.48

Why not :

b = b.setScale(2, RoundingMode.HALF_UP);

It's printing out the actual, exact value of the double.

Double.toString(), which converts doubles to Strings, does not print the exact decimal value of the input -- if x is your double value, it prints out exactly enough digits that x is the closest double to the value it printed.

The point is that there is no such double as 47.48 exactly. Doubles store values as binary fractions, not as decimals, so it can't store exact decimal values. (That's what BigDecimal is for!)


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to double

Round up double to 2 decimal places Convert double to float in Java Float and double datatype in Java Rounding a double value to x number of decimal places in swift How to round a Double to the nearest Int in swift? Swift double to string How to get the Power of some Integer in Swift language? Difference between int and double How to cast the size_t to double or int C++ How to get absolute value from double - c-language

Examples related to bigdecimal

How to use comparison operators like >, =, < on BigDecimal Convert string to BigDecimal in java Adding up BigDecimals using Streams Rounding Bigdecimal values with 2 Decimal Places How can I parse a String to BigDecimal? Rounding BigDecimal to *always* have two decimal places BigDecimal to string How to multiply a BigDecimal by an integer in Java How to round 0.745 to 0.75 using BigDecimal.ROUND_HALF_UP? Convert double to BigDecimal and set BigDecimal Precision