所以我知道为什么(7.839)=.2在SQL中的where子句中不会返回结果,而ROUND((7.839),1)=.2会返回结果,但我不知道如何向我的同事解释清楚,我想给他们提供一些可以阅读的东西,而不是我告诉他们那不会作为where子句的一部分。
谢谢你。
贾拉勒
这是由于 浮点算术. 如果你不 "明白 "的话,这可能很难解释。
我从哪里开始呢? 整数很容易用CPU能理解的位数来表示,所以,00000101被解释为5--而且正是5--因为它是2^2+2^0。 所以,00000101被解释为5--而且正是5--因为它是2^2+2^0。
然而,这对数字的小数部分并不适用。为了解决这个问题,计算机科学家发明了两种形式的数字。 一种是我个人认为的BCD(二进制编码十进制),但数据库称之为 decimal
或 numeric
. 每个数字都是一个数字。 一个数字只需要4位,所以这看起来像。
0011 0001 1111 0000 1001
3 1 . 0 9
这正好代表31. 09. 只要继续增加位数。 注意:这是概念性的。 确切的实现可能会有所不同。
第二种方法是指数记数法。 即:xxx * 2^ yyy,其中xxx和yy是整数。 例如,0.25就是1*2^(-2)。 "1 "和"-2 "可以准确地表示。
这对以下情况很有效 近似值 的数字。 问题是,0.25可以准确地表示。 但0.24和0.26不能。 它们最终会涉及一些复杂的数字。 0.2也是如此--这就是你要表示的数字。
发生的情况是,你写0.2,它被表示为0.00110011001(比如)。 但是当你进行计算时,它最终变成了0.00110011000。 哦,是这样的。 最后那个位子变了,所以其实更像0.19997(嗯,实际操作中多了点'9')。 数值并不完全相等。
寓意是:不要在浮点数字上使用平等。 这些数字可能看起来是一样的,但在一些二进制的小数位上却不同。
我在我的 "Vertica Analytic Database v9.3.1-0 "上试了一下,作为我的 SELECT VERSION()
回报:
select (7.8/39)=.2 as is_it_true
returns:
is_it_true
true
为了确保并避免任何浮点问题,请尝试将两个等价操作数转换为相同的类型。
select (7.8/39)::NUMERIC(5,1) = .2::NUMERIC(5,1)