2017-02-16 53 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, "");。它可能会编译在你的。