【问题标题】:Convert double to int in C++ without round down errors在 C++ 中将 double 转换为 int 而不会出现向下舍入错误
【发布时间】:2014-06-15 22:49:48
【问题描述】:

我有以下代码将double 转换为int

double dblValue = 7.30;
int intValue = (int)(dblValue*100);  //I want intValue to store exactly 730;
std::cout << intValue;

输出:729

我知道编译器在将 dblValue 转换为 7.2999999 之前将其读取为 int

我的问题是:是否可以通过防止向下舍入错误将其转换为730

最好避免使用 C++11 或其他预定义函数。我在这里使用的唯一预处理器指令是&lt;iostream&gt;

【问题讨论】:

  • 试试int intValue = (int)(dblValue*100.0);
  • @πάνταῥεῖ 感谢您的回复,但仍然给出 729..
  • 还有 ceil() 函数来执行显式倒圆。
  • 尝试向上取整 "int intValue = (int)((dblValue*100) + 0.5);"不完全确定这会起作用,但它应该不会受到伤害,尽管这并不漂亮。
  • 对于它的价值,我得到了 730 与您发布的确切代码,编译没有标志。

标签: c++ casting int double


【解决方案1】:

这不是任何类型的错误,而是计算机存储浮点值的方式。 你可以这样做:

int intValue = (int)(dblValue*100 + 0.00001);

【讨论】:

  • 实际上,这不仅仅是因为计算机存储浮点值的方式。将数学实数转换为数学整数也会遇到同样的问题。
  • 更不用说这不能修复负数或对半舍入
【解决方案2】:

将不是整数(在数学意义上)的数字转换为整数时,您无法防止舍入错误,您唯一能做的就是尝试实现正确的舍入。

实现合理(虽然不完美)舍入的最简单方法如下:

int intValue = (int)(dblValue < 0 ? dblValue - 0.5 : dblValue + 0.5);

当然,由于您的问题同时被标记为 c++casting,我无法抗拒用 c++ 样式转换替换您的 c 样式转换:

int intValue = static_cast<int>(dblValue < 0 ? dblValue - 0.5 : dblValue + 0.5);

【讨论】:

  • +1 我的每日投票已达到上限,但我会在这里投票!
  • @πάνταῥεῖ 该死的,我能感觉到虚假的互联网积分从我手中滑落:(
  • 范围检查会很好
  • 为什么不直接使用std::round(如果合适,将结果转换为int)?
  • @gha.st '我能感觉到假的互联网点从我手中滑过 :(' 你的身体上真的安装了任何 cyborganic SO 接口吗?;) .. . 我认为这个评论可能会鼓励其他人支持你的答案(这显然发生了)。
【解决方案3】:

您可以定义自己的整数截断函数,将值增加最小可能的量,以确保四舍五入的结果超过整数阈值。

#include <limits>

int int_cast(double x)
{
    return (int)(x * (1.0 + std::numeric_limits<double>::epsilon()));
}

如果您不想依赖 &lt;limits&gt;,您可以使用 DBL_EPSILON from &lt;float.h&gt; 或替换您自己的非常小的数字。另见this question

【讨论】:

    【解决方案4】:

    C++11 添加了lround,这有助于避免隐式双精度到长截断转换的精度损失:

    int intValue = (int) lround(dblValue*100)
    

    longint 的转换也不会降低精度。

    很遗憾,没有iround()

    更新

    我猜没有iround(),因为任何 32 位整数总是完全适合 64 位双精度的 52 个precision bits。因此,直接 double 到 int 截断不会造成精度损失:

    int intValue = (int) round(dblValue*100)
    

    【讨论】:

      猜你喜欢
      • 2012-05-04
      • 1970-01-01
      • 2012-01-13
      • 2016-05-23
      • 2015-01-22
      • 1970-01-01
      • 2016-06-28
      • 1970-01-01
      • 2011-09-17
      相关资源
      最近更新 更多