我有一个类读取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以及如何修复它?
答案 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
,当您cast
到integer
时,它会截断,因此您最终得到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。