将float转换为int时的奇怪行为

Strange bahavior when converting float to int

本文关键字:int float 转换      更新时间:2023-10-16

我有一个类读取csv文件,其中包含小数点后不超过两位数字的数字记录。

int ReadCellWithFloat(int cellNumber, int multiplier) throw (FSByFieldException)
{
    GoToCell( cellNumber );
    float number;
    FileStream >> number;
std::cout << "what we've got: " << number;
    if ( !FileStream.good() )
    {
        throw BuildException( FSByFieldException::NOT_FLOAT );
    }
    while ( multiplier-- )
    {
        number *= 10;
    }
std::cout << ' ' << number << ' ' << (int) number << std::endl;
    PassCell(); // here meaning pass comma separator
    return (int) number;
}

对于包含浮点数"8.49"的单元格,输出结果如下:

what we've got: 8.49 849 848

为什么849在转换为整数时变成848,如何修复它?

849变为848,因为纯强制转换只是截断值。所以(int) 4.8 == 4。你可能会认为8.49 * 10 * 10是849,但这并不一定是真的:)它就像架构所能表示的那样接近849,内部可能是848.999999…截断后为848。

要解决这个问题,您可以使用(int) round(number),您可能也有兴趣看看ceil()floor()函数,以及关于浮点精度问题的一般信息,以避免在数字比较和诸如此类的问题上遇到麻烦。

这是因为浮点数在二进制空间中的存储方式。这个链接将向您展示8.49的值最好表示为浮点数8.4899997。

因此,当您将float类型强制转换为int类型时,它将解析float的实际值,而不是四舍五入的值。

有几种方法可以解决这个问题:1)使用双精度(这将减轻这个问题,而不是消除它)2)使用数学库将数字848.99四舍五入。

数字8.49不能精确表示,所以当你将它乘以10两次时,你最终会得到更像848.99999的东西,当我尝试这个:

number = 8.49 ;
number *= 10 ;
number *= 10 ;
std::cout << std::fixed << number << std::endl ;

我得到848.999939,当你castinteger它被截断,所以你最终得到848。使用roundf将得到您想要的结果:

std::cout << std::fixed << roundf(number) << std::endl ;

在c++ 11中你只需要使用round