0

我有一个类读取 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 以及如何解决?

4

3 回答 3

2

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

要修复它,您可以使用(int) round(number),并且您可能也有兴趣查看ceil()floor()函数,以及有关浮点精度问题的一般信息,以避免在数字比较等方面遇到问题。

于 2013-05-17T01:15:54.227 回答
0

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

number = 8.49 ;
number *= 10 ;
number *= 10 ;

std::cout << std::fixed << number << std::endl ;

我明白了848.999939,当你cast对它integer进行截断时,你最终会得到848. 使用roundf会给你你想要的结果:

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

在 C++11 中,您只需使用round.

于 2013-05-17T01:16:02.190 回答
0

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

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

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

于 2013-05-17T01:16:29.827 回答