引言
在一次某公司的笔试题中出现了一题在一个无序的浮点数数组中找出相同的数,那么在计算机中一般的整型的十进制数一般都是直接通过“==”来判断两个数是否相等的,但是如果是浮点数还可以用这样的方式进行判断吗?答案是不行的,因为题目中的浮点数并没有指定它的精度,也就是没有说明这个数是float还是double类型的,所以直接比较大小这种方法是错误的。
样例程序
#include<iostream>
#include <bitset>
using namespace std;
int main()
{
double a = (double)0.2;
float b = (float)0.2;
unsigned long long aMem = *(unsigned long long *)&a;
unsigned long long bMem = *(unsigned long long *)&b;
bitset<32> aBit(aMem);
bitset<32> bBit(bMem);
if (a == b)
cout<<"true"<<endl;
else
cout<<"false"<<endl;
cout<<aBit<<endl;
cout<<bBit<<endl;
return 0;
}
- 运行结果
可以看到十进制的0.2,在两种不同精度的情况下,它们的二进制是不一样的,同时float的精度比double要小。
举个例子
10/3=3.333333333...
定义float的变量来存储和定义double的变量来存储,它们之间的大小是不一样的,因为精度不同。
再来看以下程序
#include<iostream>
using namespace std;
int main()
{
double a = (double)1.0;
double b = (double)0.0;
for (int i=0; i<10;++i)
b += 0.1;
if (a == b)
cout<<"true"<<endl;
else
cout<<"false"<<endl;
return 0;
}
- 运行结果
false
总结
可以看到即使两个数都是double型的,但是b在经过10次累加计算后结果却与a不同,这是为什么呢?
变量b在计算机中计算过程如下:
把值存到内存中(或高速缓存)-> CPU浮点数寄存器(精度扩展)-> CPU浮点计算单元计算 -> 浮点寄存器 -> 从新把计算结果存到内存(精度降低)
但是编译器为了优化执行效率,会把浮点数计算结果暂时存在浮点寄存器中,下次使用该值的时候就不用再从内存读取了,从而导致浮点寄存器中的值与内存中的两个相同的数精度不同,也就是直接拿浮点寄存器中的值与内存中的值进行了比较,那么两个精度不同的数大小自然不同,这就是浮点数为什么不能直接用“==”来比较的原因了,那么要怎么比较两个浮点数大小呢?可以用以下方法:
if (abs(a-b)<1e-8)
这里对两个变量a和b进行了相减操作,然后判断它们之间的误差是否要小于这个精度即可(计算环境变化这个精度取值也会有所不同)。