最近在整理笔记的时候发现了个奇怪的问题:
这段代码的输出为:
0.1
1.2
2.3
3.4
4.5
5.6
6.7
7.8
8.9
10 11.1
0
1
2
3
4
5
6
7
8
9 11
代码如下:
vector<double> testDouble; for(double i=0.1;i<=10;i+=1.1){ testDouble.push_back(i); } //遍历输出testDouble for(vector<double>::iterator testiter=testDouble.begin(); testiter!=testDouble.end();testiter++) cout<<*testiter<<" "; cout<<endl; //将testin初始化为testDouble的副本(类型转换) vector<int> testint(testDouble.begin(),testDouble.end()); //遍历输出testint for(vector<int>::iterator testintiter=testint.begin(); testintiter!=testint.end();testintiter++){ cout<<*testintiter<<" "; }
为什么会出现倒数第二对「10、9」的输出?
刚开始以为只是double转int的问题,然后测试了下:
vector<double> test; test.push_back(8.9 + 1.1); vector<int> testint(test.begin(), test.end()); cout<<*testint.begin()<<endl;
运行结果:
从结果来看并不只是转换的问题。
现在从后面的结果处可以得知:
前面计算后输出的容器元素值 8.9
与浮点常量8.9不相等
查了不少的资料才发现 问题的症结所在 :
精度问题
,计算机里的浮点数不是十进制的,所以不能精确的加出10,那个数大概是9.99999999999998(能输出10是因为 浮点数舍入
(IEEE 754)),然后转换int就成了9了(截尾)跟容器、迭代器无关。
浮点数的舍入
(摘自维基百科IEEE 754):
舍入到最接近
:舍入到最接近,在一样接近的情况下偶数优先(Ties To Even,这是默认的舍入方式):会将结果舍入为最接近且可以表示的值,但是当存在两个数一样接近的时候,则取其中的偶数(在二进制中式以0结尾的)。 朝+∞方向舍入
:会将结果朝正无限大的方向舍入。 朝-∞方向舍入
:会将结果朝负无限大的方向舍入。 朝0方向舍入
:会将结果朝0的方向舍入。 解决方案:double转(强制转换)int是截尾,可以使用round函数来四舍五入double类型的值
double round ( double );
测试下double赋值时使用round转换后的值(四舍五入了)
再来测试下 test.end()-1
和 round(test.end()-1)
结语:遇到需要强制转换数据类型的时候还是需要多注意下该类型的存储方式和运算方式,另外还要抽时间多看看IEEE标准啊。