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

时间:2013-05-17 01:03:07

标签: c++ casting

我有一个类读取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;
}

对于包含float“8.49”的单元格,输出结果为:

what we've got: 8.49 849 848

为什么849在转换为整数时转为848以及如何修复它?

3 个答案:

答案 0 :(得分:2)

849变为848,因为纯粹的强制转换会简单地截断该值。所以(int) 4.8 == 4.您可能认为8.49 * 10 * 10是849,但它不一定是真的:)它与架构所代表的一样接近849,这可能在内部类似于848.999999。 ..一旦被截断就变成848.

要修复它,您可以使用(int) round(number),您可能也有兴趣查看ceil()floor()函数以及有关浮点精度问题的一般信息,避免数字比较和诸如此类的问题。

答案 1 :(得分:0)

无法准确表示数字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

答案 2 :(得分:0)

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

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

有几种方法可以解决这个问题: 1)使用双精度(这将减轻这个问题,而不是消除它) 2)使用数学库将数字848.99向上舍入。 3)在转换为int之前,将所有数字加0.5。