我有两个浮动值:
float value1 = 1.9f;
float value2 = 20;
我想将它们相乘并得到一个确切的结果,所以我使用BigDecimal
并期望得到38:
BigDecimal total = new BigDecimal(value1).multiply(new BigDecimal(value2));
System.out.println(total); // 37.99999952316284179687500
当我用10和1.9进行相同的测试时,我得到18.99999976158142089843750而不是19。
为什么我会失去精确度?
答案 0 :(得分:2)
在javadoc中解释了BigDecimal(double)构造函数:
这个构造函数的结果可能有些不可预测。有人可能会假设在Java中编写新的BigDecimal(0.1)会创建一个BigDecimal,它恰好等于0.1(未缩放值为1,标度为1),但它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能精确地表示为double(或者,就此而言,作为任何有限长度的二进制分数)。因此,传递给构造函数的值并不完全等于0.1,尽管有外观。
虽然你的变量是浮点数,但是没有ctor采用浮点数,因此它们被视为双精度数。就像文档说的那样,如果你使用Strings作为你的价值观,你会得到你期望的确切结果(38)。
答案 1 :(得分:1)
错误恰好在开头:
float value1 = 1.9f;
您可能认为value1
现在恰好包含值1.9。但这种情况并非如此。浮点值以二进制形式存储。要记住的重要一点是,某些实数值不能用有限的数字序列表示,例如float
。 1.9是这样的数字(就像十进制一样,值1.333 ......不能用有限的数字序列表示)。
所以你应该从一开始就使用BigDecimal
。然后可以精确地表示这些值(因为它不是以二进制形式存储,而是以十进制形式存储),并且计算结果为预期答案。
答案 2 :(得分:0)
假设你的value1是double的原始类型,想要输出2个小数位,value1是350. 4432567
double roundTotal = Math.round(value1 * 100.0) / 100.0;
or
double roundTotal = (double) Math.round(value1 * 100) / 100;
Output:
350.44
Note that the 2 digits precision. Zeros indicate the wanted number of decimal to display.
Example #2
double roundTotal = (double) Math.round(value1 * 10000) / 10000;
Output:
350.4432
答案 3 :(得分:0)
您可以使用
Math.floor(float f);
//or
Math.ceil(float f);
用于确切值的函数。或者您可以为BigDecimal类重写这些函数。