C++:如何将double舍入到int?

mid*_*lue 88 c++ floating-point rounding

可能重复:
C++中float的round()

我有一个双(称为x),意味着55,但实际存储为54.999999999999943157,我刚才意识到.

所以,当我这样做

double x = 54.999999999999943157;
int y = (int) x;
Run Code Online (Sandbox Code Playgroud)

y = 54而不是55!

这困惑了我很久了.如何让它正确圆?

Mor*_*itz 115

在转换之前添加0.5(如果x> 0)或减去0.5(如果x <0),因为编译器将始终截断.

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
Run Code Online (Sandbox Code Playgroud)

C++ 11还引入了std :: round,它可能使用类似的逻辑将0.5添加到| x | 引擎盖下(如果感兴趣,请参阅链接),但显然更强大.

后续问题可能是为什么 float没有完全存储为55.有关解释,请参阅 stackoverflow答案.

  • -1此方法不考虑负数. (34认同)
  • @NickXTsui你看到最后一句了吗?"请注意,这不适用于负数." (6认同)
  • 这是不准确的,可能很慢.请参阅clang-tidy获取解释:http://clang.llvm.org/extra/clang-tidy/checks/misc-incorrect-roundings.html (3认同)
  • 我不会使用"舍入"这个短语,因为这可以解释为将"-0.5"舍入为"-1". (2认同)
  • 什么是"存储为54.999999 ......"的意思?`55`在IEEE 754的binary32中是完全可表示的.它的表示是0x425c0000.正如你所看到的,它比_完全_更多:它有足够的数字来存储你添加到它的一些小数部分.尤其是"0.5",这是2的幂. (2认同)
  • @Pac0更新了为什么这是不准确的链接:http://releases.llvm.org/5.0.2/tools/clang/tools/extra/docs/clang-tidy/checks/misc-in Correct-roundings.html (2认同)

MK.*_*MK. 46

铸造不是一种数学运算,也不是这样的.尝试

int y = (int)round(x);
Run Code Online (Sandbox Code Playgroud)

  • 演员阵容是不必要的; 结果将隐式转换为`int`. (7认同)
  • @MK:这不是促销,只是一种隐含的转换.赋值,初始化或参数传递将隐式地将任何数字类型转换为任何其他数字类型.不必要的演员阵容可能是有害的.例如,`n =(int)round(x);`看起来不错 - 但是如果`n`是`long`类型怎么办? (7认同)
  • 我永远不会记得C类型的推广规则,我认为在任何地方明确表示类型转换并没有什么坏处,它们是如此棘手的问题. (5认同)
  • @Steve #include <math.h>,STANDARDS round(),lround()和llround()函数符合ISO/IEC 9899:1999(E). (5认同)
  • 在C99和C++11中,``double round (double x);```因此,强制转换确实是必要的。链接:http://www.cplusplus.com/reference/cmath/round/ (3认同)
  • @SteveFallows:它存在于 C++11 中。 (2认同)
  • 如果你使用 `std::round(double arg)` 强制转换是必要的;但如果你使用 `std::lround(double arg)` 则不需要强制转换 (2认同)

Pub*_*bby 8

转换为int截断值.添加0.5使其进行适当的舍入.

int y = (int)(x + 0.5);
Run Code Online (Sandbox Code Playgroud)

  • 如上述评论之一所述,对负数无效.如果你这样做,可以使用'floor'而不是cast. (7认同)

小智 5

值得注意的是,您所做的不是四舍五入,而是铸造。使用(int) x强制转换会截断 的十进制值x。在您的示例中,如果x = 3.9995.9995则被截断,而x = 3.

正如许多其他人提出的那样,一种解决方案是添加0.5x,然后进行强制转换。