C++ 将float转换为int时的奇怪行为
我有一个读取csv文件的类,其中包含小数点后不超过两位数的数字记录C++ 将float转换为int时的奇怪行为,c++,casting,C++,Casting,我有一个读取csv文件的类,其中包含小数点后不超过两位数的数字记录 int ReadCellWithFloat(int cellNumber, int multiplier) throw (FSByFieldException) { GoToCell( cellNumber ); float number; FileStream >> number; std::cout << "what we've got: " << number;
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;
}
为什么转换为整数时849会转换为848以及如何修复它?849会转换为848,因为纯转换只会截断该值。所以
(int)4.8
==4。您可能认为8.49*10*10
是849,但这不一定是真的:)它与架构所能表示的849一样接近,内部可能类似于848.99999。。。一旦被截断,它就会变成848
要修复它,您可以使用
(int)round(number)
,您可能还想看看ceil()
和floor()
函数,以及有关浮点精度问题的一般信息,为了避免在数字比较等方面遇到麻烦。数字8.49
无法精确表示,因此,当您将其乘以10
两次时,您会得到更像848.99999
,当我尝试此方法时:
number = 8.49 ;
number *= 10 ;
number *= 10 ;
std::cout << std::fixed << number << std::endl ;
在C++11中,您只需使用
round
这是因为浮点数是如何存储在二进制空间中的。这将显示8.49的值最好表示为8.4899997的浮点值
因此,当您将浮点转换为int时,它将解析浮点的实际值,而不是舍入值
有几种方法可以解决此问题:
1) 使用双精度(这将消除此问题,而不是消除它)
2) 使用数学库将数字848.99四舍五入。
3) 将所有数字加上0.5,然后再将其转换为整数。请参阅此问题在中被问了数百次SO@RaymondChen我是从审查队列来到这里的,但考虑到另一个问题是关于C#的,它真的是重复的吗?原理是一样的,是的。我不熟悉任何围绕浮动的铸造实现;据我所知,这总是千真万确的。你说得对。我同意它总是截断。对不起,如果我的回答有任何地方让人困惑。我对这个问题的解决办法是在使用int(比如(int)(849.99997+0.5))之前,在数字上加上0.5。这样,您就可以避免为这个简单的任务包含数学库。数字849是完全可以表示的。问题在于8.49而不是849。@RaymondChen这确实是一个措词笨拙的问题,我修改了它以澄清它,尽管这个例子确实澄清了我的意思。
number = 8.49 ;
number *= 10 ;
number *= 10 ;
std::cout << std::fixed << number << std::endl ;
std::cout << std::fixed << roundf(number) << std::endl ;