2011-12-17 83 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()。)