BigDecimal错误

6
在Java中,我已定义k为double k=0.0; 我正在使用while循环从数据库获取数据并进行相加。
while(rst.next()) {
k = k + Double.parseDouble(rst.getString(5));
}

注意:在数据库中,我有值为125.23、458.45、665.99(所有值都有两位小数)

当我显示k时,得到的值是

k = 6034.299999999992

因此我引入了BigDecimal并将代码更改如下

      BigDecimal bd = new BigDecimal(k);
      bd = bd.setScale(2,BigDecimal.ROUND_UP);

现在我的新总数是 bd=6034.30 ,这是正确的。 问题1 问题在于当我在其他地方使用相同代码时,我得到的如下所示:
 k  = 157.3
 bd = 157.31

它应该显示为bd=157.30,因为手动添加后我得到了157.30

为什么它显示为157.31?

问题2

另外,为什么k显示这么多小数位数?下面是我得到的双精度变量k的不同值:

157.3
67.09
1014.6000000000003
229.06999999999996

有时它会显示一位小数,有时会显示两位小数,而大多数情况下它会显示14位小数值。我不太理解。

如果您有任何建议,我们将不胜感激。


为什么不像这个答案中那样定义一个单独的四舍五入函数呢? https://dev59.com/TWox5IYBdhLWcg3w44Pb#8911683这样做,并按照评论中人们的建议将k定义为BigDecimal,您将拥有干净高效的代码。 - Jav_Rock
@Jav_Rock:我正在使用函数,但这里只展示了代码... 如果需要更多细节,请告诉我... - Fahim Parkar
5个回答

7

你仍然在使用double。请在任何地方都改用BigDecimal:

BigDecimal k = BigDecimal.ZERO;
while (rst.next()) {
    k = k.add(new BigDecimal(rst.getString(5));
}

或者 - 更好的选择是,如果数据库中的字段实际上是一个十进制值:

BigDecimal k = BigDecimal.ZERO;
while (rst.next()) {
    k = k.add(rst.getBigDecimal(5));
}

6
关于你的第二个问题,double 是一种二进制浮点数。这意味着它是由二的幂次和组成的。若你要计算货币价值,请千万不要使用这些类型。(如果你在那里进行累加的话)BigDecimal 使用 十进制 算术,所以更符合我们使用的方式。
例如,0.1 这样的数字在二进制中是无限小数,即:0.000110011... 因此,使用 double 无法得到可靠和精确的结果。

3
我假设 rst 是一个 ResultSet。请确保您使用的是 getBigDecimal,而不是 Double.parseDouble(rst.getString(5))
BigDecimal k = BigDecimal.ZERO;
while(rst.next()) {
  k = k.add(rst.getBigDecimal(5));
}

首先:为什么不使用适当的SQL SUM查询直接将这些数字添加到数据库中呢?

我想在显示公司所有员工时显示总薪资... 为了执行求和,我将不得不再次发出查询,因此在 while 循环本身中我试图添加并获取所需的结果而无需第二个查询.... - Fahim Parkar

2
使用BigDecimal.ROUND_HALF_UP(或.._DOWN或.._EVEN)。
浮点计算本质上是不准确的,并且小误差会累积。这就是为什么最终结果会有一些偏差的原因。如果您始终向上舍入,像1.0000000001这样的小正误差就变成了1.01。
或者您也可以使用BigDecimal进行计算。这样,您在最终结果中就不会有误差。只需记住使用BigDecimal(String)构造函数,或直接从结果集中获取BigDecimal即可。

0

你需要将k也转换为BigDecimal,而不是double


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接