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