簡體   English   中英

浮點數舍入錯誤

[英]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.

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