2011-12-17 82 views

回答

7

当处理浮点数(单精度或双精度)时,在99%的情况下做精确的比较是徒劳的。这不仅适用于PostgreSQL,而且适用于所有使用FP算法的计算机语言。是,比显示

的三个原因,一个双重的内部表示可以包含更多的位,并且在同一时间许多号码不能使用FP(0.1是一个经常被引用的例子)表示准确且因此所有的“显示“值被截断为人类可以理解的东西(即没有像”0.099999999999999999999999999“而不是”0.1“)。

因此,一旦计算出一个要比较的数字(舍入误差)或已经从字符串转换后,就必须避免直接比较。相反,一些“范围”必须承认像

where x between 3.69334468807004 and 3.69334468807006 -- note the different numbers 

直接比较的唯一有效的情况是当值已经被刚刚预先复制的情况。一个虚构的例子是:

SELECT x, y, f1(x,y), f2(x,y), ... INTO TEMP temp_xy FROM points; 
SELECT * FROM points p JOIN temp_xy t on p.x = t.x and p.y = t.y; 

x和y已被复制,因此它们可以用作连接标准。

编辑这个和一些更漂亮的浮动的非直观问题的一个很好的开端是this article

2

您当然可以测试它是否是精度问题,只需将语句的WHERE子句扩展为范围,然后收紧该范围(通过增加更高的精度),直到您有记录或可以确认它与精度:

SELECT x(point), y(point) 
WHERE x(point) > 3.69 
    AND x(point) < 3.70 

我想看的另一件事可能是在过滤数据时使用某种其他形式的密钥。你的表是否有某种你可以使用的自然键,或者只是添加一个自动递增的字段来使用主键?

我也看到索引在涉及函数时表现不好。这张桌子上有没有索引?

3

老学校的答案:“不要仅仅为了平等比较浮点数。” (编程风格的元素,Kernighan和Plauger,1978)

为什么?因为比较两个花车的平等总是在某些情况下工作,但它几乎不会在稍有不同的情况下工作。这是由于浮点数的本质,而不是程序员的技能。

浮点数学的规范文章是What Every Computer Scientist Should Know About Floating-Point Arithmetic

对您而言,您可能可以修改the relative difference function from this C language FAQ。 (向下滚动,查找RelDif()。)