将double转换为BigDecimal并设置BigDecimal Precision

c12*_*c12 58 java double bigdecimal

在Java中,我想获取一个double值并将其转换为a 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 
    }
}
Run Code Online (Sandbox Code Playgroud)

它打印这个巨大的东西:

47.47999999999999687361196265555918216705322265625

并不是

47.48

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

我想让BigDecimal总是有两个精度单位:"47.48".BigDecimal可以限制转换为字符串的精度吗?

omn*_*nom 96

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

根据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);
Run Code Online (Sandbox Code Playgroud)

使用

BigDecimal.valueOf(val);
Run Code Online (Sandbox Code Playgroud)

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

  • 今天遇到完全相同的问题,这是恕我直言最合适的答案!谢谢! (3认同)
  • 我建议在BigDecimal.valueOf(val)之后添加.stripTrailingZeros()以省略尾随零。例如:`BigDecimal.valueOf(15.0).stripTrailingZeros();`-> 15(如果您不调用`.stripTrailingZeros()则为15.0)。 (2认同)

Gil*_*zan 47

如果您使用另一个MathContext,它会打印47.48000 :

BigDecimal b = new BigDecimal(d, MathContext.DECIMAL64);
Run Code Online (Sandbox Code Playgroud)

只需选择您需要的上下文.

  • BigDecimal b = BigDecimal.valueOf(d); (34认同)
  • 建议不要使用双构造函数. (14认同)

Jon*_*son 15

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

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

BigDecimal b = new BigDecimal("47.48")
Run Code Online (Sandbox Code Playgroud)

避免失去任何精度.


Lou*_*man 5

它正在打印出实际的,精确的值double.

Double.toString(),它转换doubles到StringS,并没有打印输入准确的十进制值-如果x是你的双重价值,它打印出足够精确的数字是x最接近double它打印的价值.

关键是没有double 47.48这样的确切.双精度值存储为二进制分数,而不是小数,因此它不能存储精确的十进制值.(那BigDecimal是为了什么!)


urO*_*ced 5

为什么不 :

b = b.setScale(2, RoundingMode.HALF_UP);
Run Code Online (Sandbox Code Playgroud)


jbi*_*der 5

在 Java 9 中,以下内容已被弃用:

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

而是使用:

BigDecimal.valueOf(d).setScale(2, RoundingMode.HALF_UP);
Run Code Online (Sandbox Code Playgroud)

例子:

    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
Run Code Online (Sandbox Code Playgroud)