【问题标题】:Rounding error with sum() on DB2DB2 上 sum() 的舍入错误
【发布时间】:2013-10-25 05:16:45
【问题描述】:

在 DB2 上添加一列时,我得到了一个糟糕的结果。数据是一个字符串,我将它通过 float() 传递到 sum()。

集合如下所示:

 AMOUNT
 --------
 0.100   
 0.250   
 0.500   
 0.050   
 0.150   
 0.150   
 0.150   
 0.600   
 0.600   
 0.150 

当我添加它时,我得到了错误的结果:

1>          select
2>              sum(float(amount)) as sum_amount
3>          from 
4>              TABLE
5>          where
6>              [CONDITIONS]
13> go
 SUM_AMOUNT
 ------------------
 2.6999999999999997

知道为什么会这样吗?有修复建议吗?

【问题讨论】:

标签: sql db2


【解决方案1】:

简短的回答是所有数据在内部都表示为二进制而不是十进制。因此,分数被“四舍五入”或更适当地以二进制格式截断。这就是为什么你正在看到你所看到的。

如果您想阅读,这里有一篇维基百科文章。 -> Floating point

现在我会劝阻你不要使用浮点数吗?如果您只是求和而不打算在总和中进行乘法或除法,我建议将其转换为小数。否则,继续将其转换为总和中的浮点数,但在一切完成后将其转换回十进制。特别是在您尝试计算加权平均值时。

【讨论】:

  • “所有数据都是......二进制而不是十进制”具有误导性。当然,所有现代内存芯片都以位存储。但至少在 DB2 (IBM) 世界中,数字经常以 10 为基数编码。Numeric 是“分区十进制”或Binary Coded Decimal。每个数字占据每个字节的下半部分,最后一个数字的上半部分包含符号,这最初与打孔卡如何表示数据有关。 Decimal 是“压缩十进制”。每个数字占半个字节,最后半个字节为符号保留。
  • 同意,“全部”具有误导性。我在浮点的上下文中回答,它以尾数 x 10 ^ 指数编码。这就是船长首先看到异常的原因。
  • 我倾向于将整数描述为二进制值,但浮点是一种数据结构。
  • 我的目标是对他所看到的内容提供一个“简单化”的解释。因此,维基百科的链接。说浮点数是一个“结构”并不会让他明白为什么他会看到小数点后的所有数字。
  • 好的。没问题,只是意见/方法的不同。 IMO 学习计算机编程的普通人应该明白,二进制一般是指二进制整数。如果“结构”令人困惑,那么深入研究浮点的内部表示和计算会更加令人困惑。
【解决方案2】:

您的答案是 FLOAT,因为输入值是 FLOAT。

浮点数,以及随后的算术,都是近似的。如果您想要精确的结果,请使用具有适当精度和小数位数的 DECIMAL 或 NUMERIC 数据类型,而不是 FLOAT。

【讨论】:

  • 另一个选项是使用DECFLOAT。但是为什么要使用它,DECNUM 会更快地为您提供您想要的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
  • 2015-07-16
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多