在C ++中将double转换为int而不会出现舍入错误

时间:2014-04-29 20:00:07

标签: c++ casting int double

我有以下代码将double投射到int

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

输出:729

I know that the compiler is reading dblValue as 7.2999999 before casting it to int.

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

如果您的解决方案避免使用C ++ 11或其他预定义函数,那将是最好的。我在这里使用的唯一预处理器指令是<iostream>

4 个答案:

答案 0 :(得分:18)

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

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

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 :(得分:1)

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

#include <limits>

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

如果您不想依赖<limits>,可以使用DBL_EPSILON中的<float.h>或替换您自己的非常小的号码。另请参阅this question

答案 2 :(得分:0)

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

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

答案 3 :(得分:-1)

C ++ 11添加了lround,有助于避免隐式double到long截断强制转换的精度损失:

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

longint施放也不会失去精确度。

不幸的是,没有iround()

<强>更新

我猜没有iround(),因为任何32位整数都将完全适合64位双精度的52 precision bits。因此,在直接双截断到int截断时不存在精度损失的可能性:

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