SELECT x(point), y(point) WHERE x(point) = 3.69334468807005
x和y的类型双精度。
我看到这个值确实在表中,但是在PostgreSQL中运行查询不会返回任何内容。为什么会这样?也许是由于精度问题?
谢谢!
SELECT x(point), y(point) WHERE x(point) = 3.69334468807005
x和y的类型双精度。
我看到这个值确实在表中,但是在PostgreSQL中运行查询不会返回任何内容。为什么会这样?也许是由于精度问题?
谢谢!
当处理浮点数(单精度或双精度)时,在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。
您当然可以测试它是否是精度问题,只需将语句的WHERE子句扩展为范围,然后收紧该范围(通过增加更高的精度),直到您有记录或可以确认它与精度:
SELECT x(point), y(point)
WHERE x(point) > 3.69
AND x(point) < 3.70
我想看的另一件事可能是在过滤数据时使用某种其他形式的密钥。你的表是否有某种你可以使用的自然键,或者只是添加一个自动递增的字段来使用主键?
我也看到索引在涉及函数时表现不好。这张桌子上有没有索引?
老学校的答案:“不要仅仅为了平等比较浮点数。” (编程风格的元素,Kernighan和Plauger,1978)
为什么?因为比较两个花车的平等总是在某些情况下工作,但它几乎不会在稍有不同的情况下工作。这是由于浮点数的本质,而不是程序员的技能。
浮点数学的规范文章是What Every Computer Scientist Should Know About Floating-Point Arithmetic。
对您而言,您可能可以修改the relative difference function from this C language FAQ。 (向下滚动,查找RelDif()。)