将double转换为BigDecimal并设置BigDecimal Precision

时间:2012-09-12 19:50:06

标签: java double bigdecimal

在Java中,我想获取一个double值并将其转换为BigDecimal并将其String值打印到一定的精度。

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 
    }
}

打印出这么大的东西:

  

47.47999999999999687361196265555918216705322265625

而不是

  

47.48

我正在进行BigDecimal转换的原因有时候,double值会包含很多小数位(即-.000012),将double转换为String时会生成科学记数法{ {1}}。我想以非科学记数法存储String值。

我希望BigDecimal总是有两个精度单位:“47.48”。 BigDecimal可以限制转换为字符串的精度吗?

8 个答案:

答案 0 :(得分:87)

这种行为的原因是打印的字符串是确切的值 - 可能不是您所期望的,但这是存储在内存中的实际值 - 它只是浮点表示的限制。

根据javadoc,如果不考虑此限制,BigDecimal(double val)构造函数行为可能会出乎意料:

  

这个构造函数的结果可能有些不可预测。一   可能会假设在Java中编写新的BigDecimal(0.1)会创建一个   BigDecimal正好等于0.1(未缩放的值为1,带有   比例为1),但它实际上等于   0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能完全表示为double(或者为此)   重要的是,作为任何有限长度的二进制分数)。因此,价值   传入构造函数的不完全等于   0.1,尽管有外表。

所以在你的情况下,而不是使用

double val = 77.48;
new BigDecimal(val);

使用

BigDecimal.valueOf(val);

BigDecimal.valueOf返回的值等于调用Double.toString(double)所产生的值。

答案 1 :(得分:45)

如果您使用其他MathContext,则会打印47.48000:

BigDecimal b = new BigDecimal(d, MathContext.DECIMAL64);

选择您需要的背景。

答案 2 :(得分:15)

您想尝试String.format("%f", d),它会以十进制表示法打印您的双倍。不要使用BigDecimal

关于精确度问题:您首先在47.48中存储double c,然后从BigDecimal创建新的double。精度的损失在于分配给c。你可以做到

BigDecimal b = new BigDecimal("47.48")

以避免失去任何精确度。

答案 3 :(得分:5)

它打印出double的实际精确值。

Double.toString()转换为double s的

String 打印输入的确切十进制值 - 如果x是你的双倍值,它打印出的数字恰好足以使x与其打印的值最接近double

关键在于与47.48完全没有double 。双倍存储值为二进制分数,而不是小数,因此它不能存储精确的十进制值。 (这就是BigDecimal的用途!)

答案 4 :(得分:5)

为什么不:

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

答案 5 :(得分:3)

String.format语法帮助我们将双精度数和BigDecimals转换为任何精度的字符串。

这个java代码:

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)));

打印:

8.88E-8
0.0000001
0.000000089
0.0000000888000000000

答案 6 :(得分:2)

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

答案 7 :(得分:0)

在Java 9中,不推荐使用以下内容:

BigDecimal.valueOf(d). <击> setScale (2, BigDecimal. <击> ROUND_HALF_UP );

改为使用:

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

示例:

    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