请教一下C++程序

bengbu

新手上路
注册
2008-05-05
消息
420
荣誉分数
39
声望点数
38
#include <iostream>

using namespace std;

int main(){


double x1=9.0;
double x2=10.0;

while (x1 < (x2-0.1)) {
x2=x2-0.1;
}

cout << x1 << ", " << x2 << endl;

}



为什么最后的输出是: 9, 9
而不是: 9, 9.1

Thanks
 
trace一哈变量x2,就什么都知道了。
 
应该用float, 不是double
 
由于精度问题 9.0<9.0 在内存实现时有可能成立,所以会多做一个循环。如果要确保不多做一个循环,应该用类似 9.0-9.0<0.000001,(根据精度需要)
 
由于精度问题 9.0<9.0 在内存实现时有可能成立,所以会多做一个循环。如果要确保不多做一个循环,应该用类似 9.0-9.0<0.000001,(根据精度需要)

你的意思是有可能是9,9也可能是9,9.1?
 
就应该是 9,9
最后一次满足的条件是 9 〈 9.1, 进入循环体再做一次 X2 = 9.1 - 0.1 = 9
 
由于精度问题 9.0<9.0 在内存实现时有可能成立,所以会多做一个循环。如果要确保不多做一个循环,应该用类似 9.0-9.0<0.000001,(根据精度需要)

不对。9.0<9.0是在那都是一定不成立的;是9.1-0.1=9.0在内存表示上不一定成立,所以才有可能x2给跑到了9。
 
就应该是 9,9
最后一次满足的条件是 9 〈 9.1, 进入循环体再做一次 X2 = 9.1 - 0.1 = 9
看题不仔细,那是 while (X1 < X2 - 0.1), 不是 while(X1 < X2).
 
不对。9.0<9.0是在那都是一定不成立的;是9.1-0.1=9.0在内存表示上不一定成立,所以才有可能x2给跑到了9。
好更正一下。我说的9.0 < 9.0 就是 9.1-0.1<9.0 的意思。总之,两个 double 直接比较是很危险的。因为具体结果同具体的机器硬件有关。16 位,32位,64位可能得到不同结果。正确的应该是 d1-d2<可接受精度。这样保证代码的可移植性。
 
按照gina_z的建议,

将x1, x2定义为float类型,最后的输出是: 9, 9.1
而将x1, x2定义为double类型, 最后的输出是: 9, 9

为什么?
 
好更正一下。我说的9.0 < 9.0 就是 9.1-0.1<9.0 的意思。总之,两个 double 直接比较是很危险的。因为具体结果同具体的机器硬件有关。16 位,32位,64位可能得到不同结果。正确的应该是 d1-d2<可接受精度。这样保证代码的可移植性。


#include <iostream>

using namespace std;

int main(){

double x1=9.0;
double x2=10.0;

while (0.1 < (x2-x1)){
x2=x2-0.1;
}
cout << x1 << " " << x2 << endl;
system("pause");

}


按照您的建议,改了判断,但结果仍是依旧。

将x1, x2定义为float类型,最后的输出是: 9, 9.1
而将x1, x2定义为double类型, 最后的输出是: 9, 9

为什么?
 
浮点数,包括float和double的比较都是不精确的

即使您这次用float似乎得到了你想要的结果,也不表明下次别的浮点运算就能准确。常用的一个方法是在你的判断式中加上一个误差,从而能够抵消有限位计算机表示无限精确数字(理论上)时不可避免的误差。
比如:
delta = 1e-32;

while (x1 < x2-0.1-delta){
...
}

应该能够保证你得到想要的结果,即使你用double类型。
delta的设置与特定机器的精度有关。你可以GOOGLE一下你的机器上double的精度,从而确定最小的delta值。当然对于已知的问题,delta大一点也没关系。

注意 +/- delta 的应用。其实更常见的是要比较两个float或double是否相等 (比如在解不定方程时那样)。如果你需要断定X1是否等于X2(在浮点运算中实际上是不可能的),你就需要用到

#define eq(x1, x2) (x1 > x2-delta) && (x1 < x2+delta) ? 1:0

(不好意思,C/C++的句法有点忘了,基本意思如此)
 
后退
顶部