簡體   English   中英

當需要使用float時,如何真正避免浮點錯誤?

[英]How to actually avoid floating point errors when you need to use float?

我正在嘗試使用一些UI按鈕將位置偏移0.1或-0.1來影響3D模型的轉換。

我的模型位置是三維浮點數,因此將0.1f簡單地添加到其中一個值會導致明顯的舍入誤差。 雖然我可以使用BigDecimal之類的東西來保持精度,但我仍然必須將其從浮點數轉換為最后的浮點數,並且它始終會產生愚蠢的數字,使我的UI看起來一團糟。

我可以將顯示的值設為漂亮,但舍入錯誤只會隨着更多的編輯而變得更糟,它們會使我的保存文件變得很難閱讀。

那么,當我需要使用浮點數時,如何真正避免這些錯誤?

Kahan求和成對求和算法有助於減少浮點錯誤。 這是Kahan算法的一些Java代碼

我將使用Rational類。 那里有很多- 看起來應該可以工作。

Rational渲染為float時,一項重大代價將是將分母簡化為gcd 我發布的那一刻始終使分子和分母始終處於完全還原狀態,如果您總是加或減1/10,這應該是非常有效的。

實現將值歸一化(即具有一致的符號),但未歸約。

您應該選擇最適合您的用法的實現。

一個簡單的解決方案是使用固定精度。 即您想要的整數10倍或100倍。

float f = 10;
f += 0.1f;

變成

int i = 100;
i += 1;  // use an many times as you like
// use i / 10.0 as required.

在任何情況下我都不會使用float ,因為舍入錯誤會比double而不是無用(除非您有數百萬個浮點值), double精度會給您8位數的精度,並且具有合理的舍入不會看到那些錯誤。

如果堅持使用浮點數:避免錯誤的最簡單方法是使用精確的浮點數,但要接近所需的值,即

round(2 ^ n *值)* 1/2 ^ n。

n是位數,值要使用的位數(在您的情況下為0.1)

在您的情況下,精度越來越高:

n = 4 => 0.125
n = 8(字節)=> 0.9765625
n = 16(短)=> 0.100006103516 ....

長數鏈是二進制轉換的偽像,實數的位數少得多。

由於浮點數是精確的,因此加法和減法不會引入偏移誤差,但只要位數不超過浮點值保持,就始終可以預測。

如果您擔心使用此解決方案會損害顯示效果(因為它們是奇數浮點數),請僅使用和存儲整數(步長為-1/1)。 內部設置的最終值是

x =值*步驟。

隨着步長增加或減少1,將保持精度。

暫無
暫無

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

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