将double转换为BigDecimal并设置BigDecimal Precision

在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.2E-4 。 我想以非科学记数法存储string值。

我想让BigDecimal总是有两个精度单位,例如:“47.48”。 BigDecimal是否可以限制转换为string的精度?

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

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

只要select你需要的上下文。

这种行为的原因是打印的string是确切的值 – 可能不是你所期望的,但这是存储在内存中的真实值 – 这只是浮点表示的限制。

根据javadoc,如果不考虑这个限制,BigDecimal(double val)构造函数的行为可能是意料之外的:

这个构造函数的结果可能有些不可预知。 有人可能会认为在Java中编写新的BigDecimal(0.1)会创build一个正好等于0.1的BigDecimal(非缩放值为1,标度为1),但实际上它等于0.1000000000000000055511151231257827021181583404541015625。 这是因为0.1不能完全表示为双(或者就此而言,作为任何有限长度的二进制分数)。 因此,传递给构造函数的值并不完全等于0.1,尽pipe如此。

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

 double val = 77.48; new BigDecimal(val); 

使用

 BigDecimal.valueOf(val); 

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

你想尝试String.format("%f", d) ,这将打印你的双十进制符号。 根本不要使用BigDecimal

关于精度问题:你首先在double c存储47.48 ,然后从这个double创build一个新的BigDecimal 。 精确度的损失是分配给c 。 你可以做

 BigDecimal b = new BigDecimal("47.48") 

以避免失去任何精度。

它打印出double的实际值。

double s转换为String s的Double.toString() 不会输出input的精确十进制值 – 如果x是您的double值,则会打印出足够多的数字,即x是与打印的值最接近的double

重点是没有 47.48 这样的double 。 将商店值加倍为二进制分数,而不是小数,所以它不能存储精确的十进制值。 (这就是BigDecimal目的!)

String.format语法可以帮助我们将double和BigDecimals转换为任何精度的string。

这个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 

为什么不b = b.setScale(2,RoundingMode.HALF_UP);

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