在c ++中将double转换为int输1

时间:2012-01-09 09:14:00

标签: c++ double type-conversion

  

可能重复:
  Why does this double to int conversion not work?

在c ++中将double转换为int lost 1

#include <iostream>
#include <cmath>
using namespace std;

void main() {

    double num = 1234.34;
    int numInt = num;
    double numAfterPoint = num - numInt; // 0.34

    int counter = 1;
    double numFloatPower = numAfterPoint;

    while (true) {
        numFloatPower = numAfterPoint * pow(10.0, counter);
        cout << numFloatPower << " > " << (int)numFloatPower << " ";
        system("pause");
        counter++;
    }

}

目前的结果:

3.4 > 3 Press any key to continue . . .
34 > 33 Press any key to continue . . .
340 > 339 Press any key to continue . . .
3400 > 3399 Press any key to continue . . .

结果应该是:

3.4 > 3 Press any key to continue . . .
34 > 34 Press any key to continue . . .
340 > 340 Press any key to continue . . .
3400 > 3400 Press any key to continue . . .
等等......

5 个答案:

答案 0 :(得分:5)

cast-to-int操作(int)doubleValue执行截断,这意味着如果数字在内部表示为33.999999999 ......它将被截断为33。

如果您需要进行舍入(3.9→4,3.4→3),请使用round()


注意:

  • 1234.34实际上是1234.33999999999991814547684044...,因为它无法使用有限数量的二进制数字来精确表示,所以在第53位它将被四舍五入
  • 因此你的0.34实际上是0.33999999999991814547684044 ......,
  • 您的3.4实际上是3.3999999999991814547684044 ...,
  • 你的34实际上是33.999999999991814547684044 ......,
  • 你的340实际上是339.99999999991814547684044 ......,

答案 1 :(得分:3)

浮点算术使用2的幂的有限和来表示任意数。诸如3.4之类的数字可以是舍入的,其不是两个幂的总和。在这种情况下,它稍微向下舍入,比如3.39996…。然后,当您乘以时,结果将为33.9996…,在圆到零规则下将向下舍入为33

C ++控制台I / O足够智能,可以根据显示的十进制数字来舍入到最接近的偶数,但计算机的内部数学电路却不知道。它使用值的完整精度,在这种情况下包含错误。

尝试cout << setprecision( 20 );查看丑陋的事实。

答案 2 :(得分:1)

为了帮助您了解正在发生的事情,让我用固定的小数位数给出一个非常简单的类似问题的解释。 (你遇到的问题是由于固定的二进制位置,更难以理解,但问题是相同的。)

表示1/3的最佳效果是.333333。但现在3 * 1/3 != 1

您可以将2/3表示为.666666,然后2 * 1/3 = 1/3,然后2/3 + 1/3 != 1

您可以将2/3表示为.666667,然后2/3 + 1/3 = 1,然后再2/3 - 1/3 - 1/3 != 02 * 1/3 != 2/3

由于四舍五入和精度有限,您不应期望浮点数学能够产生完全正确的结果。

正如1/3没有精确的十进制表示,.34没有精确的二进制表示。

答案 3 :(得分:1)

问题是你的第一个假设是假的:

double num = 1234.34;
int numInt = num;
double numAfterPoint = num - numInt; // 0.34


std::cout << std::setprecision(17) << numAfterPoint << "\n";

3.3999999999991815

现在,如果您在主循环中设置精度,您将得到以下数字。

3.3999999999991815 > 3 
33.999999999991815 > 33 
339.99999999991815 > 339 
3399.9999999991815 > 3399

问题是流打印代码在打印前将结果四舍五入,导致打印3.4而不是3.3999999999。这是因为3.4不能用二进制浮点数精确表示。

答案 4 :(得分:0)

由于十进制数通常不能完全用二进制表示,num不是1234.34,而是与该数字最接近的double值。那一个可能略小于1234.34(比方说,1234.3399999999999999999999999);在这种情况下,当然numAfterPoint也略小于0.34,使100 * numAfterPoints小于34等等。由于转换为int会删除小数部分,即使它非常接近1,您将会得到33而不是34。

另一方面,如果直接输出浮点值,则舍入到特定的位数(可以使用流操作符控制)。因此,除非您告诉流输出很多数字,否则您看不到差异。尝试

std::cout << std::setprecision(20) << numAfterPoint << '\n';

查看真正存储的值。