繁体   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