我最近在一个项目中开始使用Sonar,并且我得到了关于使用构造函数new BigDecimal(double val)
的PMD规则。当我阅读java文档时,我发现新的BigDecimal(double val)有点不可预测,我应该使用可预测的new BigDecimal(String val)
。
以下是javadoc对BigDecimal
public BigDecimal(double val)
所说的内容:
将double转换为BigDecimal,这是精确的小数 double的二进制浮点值的表示。规模 返回的BigDecimal是最小的值,(10scale× val)是一个整数。
注意:
这个构造函数的结果可能有些不可预测。一 可能会假设在Java中编写
new BigDecimal(0.1)
会创建一个BigDecimal
正好等于0.1(未缩放值为1, 比例为1),但它实际上等于 0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能完全表示为double(或者为此) 重要的是,作为任何有限长度的二进制分数)。因此,价值 传入构造函数的不完全等于 0.1,尽管有外表。另一方面,String构造函数是完全可预测的: 撰写
new BigDecimal("0.1")
会创建一个BigDecimal
正如人们所期望的那样,正好等于0.1。因此,一般来说 建议首先使用String构造函数 之一。当必须将double用作
BigDecimal
的来源时,请注意 这个构造函数提供了精确的转换;它没有给出 使用。将double转换为String的结果相同Double.toString(double)
方法,然后使用BigDecimal(String)
构造函数。要获得该结果,请使用静态valueOf(double)
方法。
为什么这个构造函数确实存在?这个问题不够new BigDecimal(String val)
吗?我什么时候应该使用new BigDecimal(double val)
构造函数?
答案 0 :(得分:7)
为什么这个构造函数确实存在?
它将实际表示的double
值转换为BigDecimal。 BigDecimal的重点是提供尽可能多的精度,这就是这个构造函数的作用。
如果你想通过少量四舍五入来获得你可以使用的Double.toString(double)
用途的价值
System.out.println(BigDecimal.valueOf(0.1));
打印
0.1
何时应该使用新的BigDecimal(双val)构造函数
当你想知道double
真正代表的价值时。您可以根据需要应用自己的舍入。
当您使用double
时,您应该始终应用合理的舍入。但是,如果你这样做,你可能会发现你不需要BigDecimal。 ;)
答案 1 :(得分:2)
因为如果您已经以double
值作为数据开头,那么您已经失去了这种精确度。因此,没有它会迫使您将String
转换为BigDecimal
以将其转换回来。
而且,有时候你可能只需要那个值。
答案 2 :(得分:2)
When should I use the new BigDecimal(double val) constructor?
最好 - 无处。
如果您愿意使用BigDecimals,那么使用带有双精度的构造函数会失去确切数字表示的所有好处。
Why does this constructor really exists?
因为有时你只有两倍,你想要翻译成BigDecimal。强迫你在中间使用.toString()
会很愚蠢;)
答案 3 :(得分:1)
当您要使用的数据已作为double值存在时,您将使用double构造函数。
,在将其转换为BigDecimal之前将其转换为字符串将是一种浪费答案 4 :(得分:0)
我想发表评论,但无法想出如何将“代码”放入评论中,所以我回答:
double val = 0.1; // this is not 0.1, but an approximination as pointed out in other answers.
BigDecimal biggy = new BigDecimal(val); // this variable conatains the "same" value as val does, however it is not 0.1, but as pointed out in other answers: 0.100000000000000005551115123
因此,在此处列出的情况下,您可以完全控制源代码,您应该将 val 写为'String val =“0.1”'
但是,如果您从文件中读取二进制双精度数,则构造函数BigDecimal(double val)
非常有用。显然你几乎在所有情况下都会想要与'双打'完全相同的BigDecimals
答案 5 :(得分:0)
不可预测?我不同意。
final double before = 0.1;
BigDecimal bd = new BigDecimal(before);
double after = bd.doubleValue();
assert before == after;
理解的关键:
assert 0.1 == 0.1000000000000000055511151231257827021181583404541015625;
如果你的确意味着“0.1”,那么是的,使用String构造函数=)但是如果你已经有double
,那么那个double不是“0.1”。
你引用的JavaDoc说:
当必须将double用作BigDecimal的源时,请注意 此构造函数提供完全转换;
我没有看到确切的转换是如何“不可预测的”,我非常赞成从这句话中删除“必须”这个词。
在一天结束时,两个构造函数都按预期工作。如果你有字符串“0.1”,那么BigDecimal(String)会完全转换这个值。如果你有一个双0.1,那么BigDecimal(double)将完全转换这个值。