我有一个双精度(称之为x),本来是55,但实际上存储为54.999999999999943157,我刚刚意识到。
所以当我这样做时
double x = 54.999999999999943157;
int y = (int) x;
y = 54 而不是 55!
这让我困惑了很长时间。如何让它正确舍入?
在投射前加 0.5(如果 x > 0)或减去 0.5(如果 x < 0), because the compiler will always truncate.
float x = 55; // stored as 54.999999...
x = x + 0.5 - (x<0); // x is now 55.499999...
int y = (int)x; // truncated to 55
C++11 还引入了 std::round,它可能使用类似的逻辑,将 0.5 添加到 |x|在引擎盖下(如果感兴趣,请参阅链接),但显然更强大。
后续问题可能是为什么浮点数没有精确存储为 55。有关解释,请参阅this stackoverflow 答案。
铸造不是数学运算,也不是这样的。 尝试一下
int y = lround(x);
转换为
int
会截断该值。添加 0.5
会使其进行适当的舍入。
int y = (int)(x + 0.5);
值得注意的是,你所做的不是舍入,而是铸造。使用
(int) x
进行转换会截断 x
的小数值。正如您的示例中所示,如果 x = 3.9995
,则 .9995
会被截断并且 x = 3
。
正如许多其他人所建议的,一种解决方案是将
0.5
添加到 x
,然后进行投射。
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double x=54.999999999999943157;
int y=ceil(x);//The ceil() function returns the smallest integer no less than x
return 0;
}