C++ 在c+中将double转换为int lose 1+;

C++ 在c+中将double转换为int lose 1+;,c++,double,type-conversion,C++,Double,Type Conversion,可能重复: 在c中将double转换为int lose 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 n

可能重复:

在c中将double转换为int lose 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 > 34 Press any key to continue . . .
340 > 340 Press any key to continue . . .
3400 > 3400 Press any key to continue . . .

等等。

浮点运算使用两个幂的有限和来表示任意数字。诸如
3.4
之类的数字不完全是二的幂和,可以四舍五入。在本例中,它稍微向下舍入,即
3.39996…
。然后,当您进行乘法运算时,结果将是
33.9996…
,在从四舍五入到零的规则下,结果将向下四舍五入到
33

C++控制台I/O足够智能,可以根据显示的小数位数四舍五入到最接近的偶数,但计算机的内部数学电路对此一无所知。它使用值的全部精度,在本例中包含错误


尝试
cout强制转换为int操作
(int)doubleValue
执行截断,这意味着如果数字在内部表示为33.99999999。。。它将被截断为33

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


注:

  • 1234.34实际上是因为它不能用有限数量的二进制数字精确表示,所以在第53位它将被舍入
  • 因此,您的0.34实际上是0.3399999991814547684044
  • 你的3.4实际上是3.399999991814547684044
  • 你的34实际上是33.9999999991814547684044
  • 你的340实际上是339.9999999 1814547684044
  • 等等

为了帮助您理解发生了什么,让我用固定小数位数对类似问题进行一个非常简单的解释。(您遇到的问题是由于固定的二进制位置造成的,这很难理解,但问题是相同的。)

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

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

您可以将
2/3
表示为
.66666 7
,然后
2/3+1/3=1
,但随后
2/3-1/3-1/3!=0和
2*1/3!=2/3

由于四舍五入和精度有限,您不应该期望浮点运算产生完全正确的结果


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

由于十进制数通常不能用二进制表示,因此
num
不是1234.34,而是与该数字最接近的
双精度值。该值可能略小于1234.34(例如,1234.33999999999999999);在这种情况下,当然
numAfterPoint
也略小于0.34,使得100*numAfterPoints明显小于34等。由于转换为int会删除小数部分,即使它非常接近1,也会得到33而不是34

另一方面,如果直接输出浮点值,它将四舍五入到特定的位数(可以使用流操纵器进行控制)。因此,除非您告诉流输出非常多的数字,否则您不会看到差异。试一试

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

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

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


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

3.3999999999991815

问题在于流式打印代码在打印前对结果进行四舍五入,导致它打印
3.4
,而不是
3.399999999
。这是因为3.4不能准确地用二进制浮点数表示。

您能详细说明一下这个问题吗,您期望得到什么和得到什么。那么您的问题是什么?结果是什么?您对它有什么问题?您为什么要首先做这个练习?这很好地解释了这一点:
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