2017-02-16 52 views
0
#include<iostream> 

long myround(float f) 
{ 
    if (f >= UINT_MAX) return f; 
    return f + 0.5f; 
} 

int main() 
{ 
    f = 8388609.0f; 
    std:cout.precision(16); 
    std::cout << myround(f) << std::endl; 
} 

輸出:8388610.0浮動舍入誤差

我試圖使輸出的感覺。大於 8388609.0的下一個浮點數是8388610但是爲什麼四捨五入的值不是8388609?

+1

_「下一個大於8388609.0的浮點數是8388610」_你是如何得出這個結論的? –

+0

單精度浮點數沒有足夠的空間來保證表示所有這些十進制數字(多於六個)。你想要做什麼? –

+0

此代碼不能編譯。你沒有'f'的聲明。張貼您的_actual_ [MCVE],導致規定的輸出。 –

回答

1

IEEE-754定義了幾種可能的舍入模式,但實際上,幾乎總是使用的是「舍入到最近,偶數」。這也被稱爲「銀行家四捨五入」,因爲任何人都無法辨別。

「連接到偶數」表示如果浮點計算的舍入結果恰好在兩個可表示數字之間的中間位置,舍入將在任何方向上使結果的LSB爲零。在你的情況下,8388609.5在8388609和8388610之間,但只有後者在最後一位爲零,所以四捨五入是向上的。如果您通過了8388610.0,結果會向下舍入;如果您通過了8388611.0,則會向上舍入。

+0

感謝您的解釋。解答我的問題。另外,我假定浮點硬件決定了舍入必須如何完成。這是否意味着FP硬件實際計算精確值並基於舍入策略映射到可表示的浮點表示? – KodeWarrior

+0

這回答了我關於FP硬件的問題。 http://pages.cs.wisc.edu/~markhill/cs354/Fall2008/notes/flpt.apprec.html – KodeWarrior

1

如果您將示例更改爲使用double,那麼錯誤消失。問題是float在它可以存儲的有效位數中比double更有限。將0.5添加到您的值只會超出浮點的精度限制,導致它執行一些舍入操作。在這種情況下,8388609.0f + 0.5f == 8388610.0f

#include<iostream> 

long myround(double f) 
{ 
    if (f >= UINT_MAX) return f; 
    return f + 0.5; 
} 

int main() 
{ 
    double f = 8388609.0; 
    std::cout.precision(16); 
    std::cout << myround(f) << std::endl; 
} 

如果您繼續向您的號碼添加數字,最終也會失敗double

編輯: 您可以使用static_assert輕鬆測試。這編譯在我的平臺static_assert(8388609.0f + 0.5f == 8388610.0f, "");。它可能會編譯在你的。