num1 = 0.1
num2 = 0.2
num3 = 0.3
num4 = num1 + num2
if num3 == num4:
print("y")
else:
print("n")
结果是n
0.1和0.2 相加 不等于 0.3
0.1+0.2=0.30000000000004
原因
两浮点数X,Y进行加减运算时,必须按以下几步执行(可参考 [4] 中插图):
(1)对阶,使两数的小数点位置对齐,小的阶码向大的阶码看齐。
(2)尾数求和,将对阶后的两尾数按定点加减运算规则求和(差)。
(3)规格化,为增加有效数字的位数,提高运算精度,必须将求和(差)后的尾数规格化。
(4)舍入,为提高精度,要考虑尾数右移时丢失的数值位。
(5)判断结果,即判断结果是否溢出。
关键就在与对阶这一步骤,由于float的有效位数只有7位有效数字,如果一个大数和一个小数相加时,会产生很大的误差,因为尾数得截掉好多位。例如:
123 + 0.00023456 = 1.23*10^2 + 0.000002 * 10^2 = 123.0002
那么此时就会产生0.00003456的误差,如果累加多次,则误差就会进一步加大。
解决方案
- Kahan summation算法
解决方法就是把多余的误差部分算出来©,再在下一次循环减去这个误差
2.二分法递归计算加法,这样会没有误差,但是函数调用消耗大(尤其是多次)
int main()
{
float f = 0.1;
float sum = 0;
sum+=add(f,4000000);
cout<<sum<<endl;
return 0;
}
float add(float f,int count)
{
if(count==1)
return f;
else
return add(f,count/2)+add(f,count-count/2);
}
3.使用double,精度更高
4.ieee浮点数,为了规格化,精度每超过2的整数次幂,精度要下降一位,
你的f是0.1,float位数是23,当sum足够大的时候,会出现 sum+f==sum 的情况,这个是ieee标准,和C++没关系,事实上编译器应该已经做了浮点精度调整了。