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