簡體   English   中英

Java中浮點數的比較

[英]Comparison of floating point numbers in Java

可以說,我有以下內容:

float x= ...
float y = ...

我想做的就是比較它們是否x大於y。 我對他們的平等不感興趣。

我的問題是,僅對浮點值執行>或<檢查時,應該考慮精度嗎? 我是否正確假設僅在進行相等性檢查時才考慮精度?

由於您已經有兩個浮點數,分別命名為x和y,並且如果以前沒有任何類型轉換,則可以輕松地使用“>”和“ <”進行比較。 但是,假設您有兩個d1> d2的雙精度數d1和d2,並將它們分別轉換為f1和f2,則由於精度問題,可能會得到f1 == f2。

已經有了不需要發明的輪子:

if (Float.compare(x, y) < 0)
    // x is less than y

所有float值都具有相同的精度。

這實際上取決於這兩個浮標來自何處。 如果在計算中較早進行了舍入,則如果累積的舍入足夠大以至於超過“理想”答案之間的差,則可能無法獲得任何比較值所期望的結果。

通常,浮點數的任何比較都必須視為模糊。 如果必須執行此操作,則您有責任了解舍入錯誤的來源,並確定是否在乎它,以及如何處理它。 通常最好避免完全比較浮點數,除非您的算法絕對要求這樣做...並且如果必須這樣做,請確保“接近但不太完全”的比較不會破壞您的程序。 您可能能夠重組公式和計算順序,以減少精度損失。 增大一倍將減少累積的誤差,但這不是一個完整的解決方案。

如果必須比較,並且比較很重要,請不要使用浮點數。 如果您需要像浮點數這樣的絕對精度,請使用像bignums這樣的無窮大數學包或有理數實現,並接受性能成本。 或切換到可縮放的整數-也會四舍五入,但以對人類更有意義的方式進行四舍五入。

這是一個難題。 答案確實取決於您如何獲得這些數字。


首先,您需要了解浮點數是精確的,但是它們不一定代表您認為的數字。 典型編程語言中的浮點類型表示無限的實數集的有限子集。 因此,如果您有一個任意的實數,則很可能無法使用float型或double float型精確表示它。 事實上 ...

可以完全一樣來表示的唯一實數floatdouble值具有形式

  mantissa * power(2, exponent) 

其中“尾數”和“指數”是規定范圍內的整數。

結果是,大多數“十進制”數字也沒有精確的floatdouble float表示形式。

因此,實際上,我們最終得到這樣的結果:

 true_value = floating_point_value + delta,

其中“ delta”是錯誤; 即,真實值與floatdouble float值之間的差異很小(或不太小)。


接下來,當您使用浮點值執行計算時,在某些情況下無法將精確結果表示為浮點值。 一個明顯的例子是:

1.0f / 3.0f 

其真實值是0.33333 ...重復出現,在任何有限的基數2(或基數10!)浮點表示中都無法表示。 相反,發生的結果是通過四舍五入到最接近的floatdouble值產生了結果...引入了更多錯誤。

隨着您執行越來越多的計算,錯誤可能增加或保持穩定,具體取決於執行的操作順序。 (有一個數學分支處理此問題:數值分析。)


回到您的問題:

“僅對浮點值執行>或<檢查時,是否應該考慮精度?”

這取決於您如何獲得這些浮點值,以及相對於它們名義上表示的真實Real值的“增量”值的了解。

  • 如果沒有錯誤(即delta <值的最小可表示差異),則可以使用==<>安全地進行比較。

  • 如果存在可能的錯誤,那么您需要考慮這些錯誤...如果比較的語義旨在根據(名義)真實值進行比較。 此外,在編寫比較代碼時,您需要對“增量”(累積誤差)有一個可靠的估計。

簡而言之,沒有簡單(正確)的答案...

“我是否正確假設僅在進行相等性檢查時才考慮精度?”

實際上,在任何比較運算符中都沒有“考慮精度”。 這些運算符將操作數視為精確值,並進行相應比較。 您的代碼將根據先前計算的錯誤估計值來考慮精度問題。


如果您對增量進行了估算,那么數學上的<比較將是這樣的:

// Assume true_v1 = v1 +- delta_v1 ... (delta_v1 is a non-negative constant)

if (v1 + delta_v1 < v2 - delta_v2) {
    // true_v1 is less than true_v2
}

等等 ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM