[英]Float rounding off error
#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?
如果將示例更改為使用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, "");
。 它可能會在您的計算機上編譯。
IEEE-754定義了幾種可能的舍入模式,但是實際上,幾乎總是使用的一種模式是“舍入到最接近,聯系到偶數”。 這也被稱為“銀行家四舍五入”,任何人都無法辨別。
“連為平”表示如果浮點計算的待取整結果恰好位於兩個可表示數字的中間,則取整將在使結果的LSB為零的任何方向上進行。 在您的情況下,8388609.5在8388609和8388610之間,但只有后者的最后一位為零,因此舍入是向上的。 如果您已通過8388610.0,則結果將向下舍入;否則,將向下舍入。 如果您已通過8388611.0,它將向上舍入。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.