在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 . . .
等等......
答案 0 :(得分:5)
cast-to-int操作(int)doubleValue
执行截断,这意味着如果数字在内部表示为33.999999999 ......它将被截断为33。
如果您需要进行舍入(3.9→4,3.4→3),请使用round()
。
注意:
答案 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 != 0
和2 * 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';
查看真正存储的值。