【问题标题】:C++: How to round a double to an int? [duplicate]C++:如何将 double 舍入为 int? [复制]
【发布时间】:2012-03-14 03:01:18
【问题描述】:

我有一个 double(称为 x),本来是 55,但实际上存储为 54.999999999999943157,这是我刚刚意识到的。

所以当我这样做时

double x = 54.999999999999943157;
int y = (int) x;

y = 54 而不是 55!

这让我困惑了很久。我怎样才能让它正确地四舍五入?

【问题讨论】:

  • 您可以将 0.5 添加到数字,然后进行强制转换以使其截断为 int。是否需要舍入负数?
  • 你可以使用这个预处理器定义:#define ROUND_2_INT(f) ((int)(f >= 0.0 ? (f + 0.5) : (f - 0.5)))
  • 实际上 54.999999999999943157 在 完全可表示 55 以下 8 个 ULP,如果 double 你的意思是来自 IEEE 754 的 binary64。所以这不是 55 的实际存储方式,而是你的计算有多不精确。
  • 在将负输入转换为 int 之前将 +0.5 添加到负输入会给出错误的答案。正确的快速和肮脏的方法是测试输入符号

标签: c++ floating-point rounding


【解决方案1】:

在转换前加 0.5(如果 x > 0)或减去 0.5(如果 x

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,它可能使用了类似的逻辑,将 |x| 加 0.5。在引擎盖下(如果有兴趣,请参阅链接),但显然更强大。

后续问题可能是为什么浮点数没有准确存储为 55。有关说明,请参阅 thisstackoverflow 答案。

【讨论】:

  • 我不会使用“向下舍入”这个短语,因为这可能会被解释为将-0.5 舍入到-1。
  • -1 此方法不考虑负数。
  • @NickXTsui 你看到最后一句话了吗? “请注意,这不适用于负数。”
  • stored as stored as 54.999999... 是什么意思? 55 完全可以用 IEEE 754 的 binary32 表示。它的表示是 0x425c0000。如您所见,它不仅仅是精确:它有很多数字来存储您添加到其中的一些小数部分。 0.5 尤其如此,它是 2 的幂。
  • 这是不准确的,可能很慢。查看 clang-tidy 的解释:clang.llvm.org/extra/clang-tidy/checks/…
【解决方案2】:

铸造不是数学运算,也不是这样的。试试

int y = (int)round(x);

【讨论】:

  • 演员表是不必要的;结果将隐式转换为int。
  • 我永远记不住 C 类型提升规则,我认为在任何地方明确声明类型转换并没有什么坏处,它们是一个棘手的问题。
  • @Steve #include ,标准 round() 、 lround() 和 llround() 函数符合 ISO/IEC 9899:1999(E)。
  • @MK.:这不是促销,只是隐式转换。赋值、初始化或参数传递会将任何数字类型隐式转换为任何其他数字类型。不必要的演员表可能是有害的。例如,n = (int)round(x); 看起来不错——但如果 n 的类型是 long 呢?
  • 在 C99 和 C++11 中,double round (double x); 因此,确实需要强制转换。链接:cplusplus.com/reference/cmath/round
【解决方案3】:

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

int y = (int)(x + 0.5);

【讨论】:

  • 对负数无效,如上面的 cmets 之一所述。如果你这样做,可以使用 'floor' 而不是 cast。
【解决方案4】:

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

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

【讨论】:

  • 谢谢,实际上我才意识到我什至需要四舍五入(我在我的程序中只使用整数)
【解决方案5】:
#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;
}

【讨论】:

  • 这会强制数字上升... 54.000000000000001 将变为 55。
  • @AlbertRenshaw,对 - 这意味着这个答案是错误的。
猜你喜欢
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
  • 2014-12-08
  • 1970-01-01
  • 1970-01-01
  • 2021-08-14
  • 2021-12-18
相关资源
最近更新 更多