Console.WriteLine(7.88 + 5.00 == 12.88);结果是什么呢?
结果为False,是的哦,为什么会这样呢?
分析
用"=="来比较两个double应该相等的类型,返回真值完全是不确定的。计算机对浮点数的进行计算的原理是只保证必要精度内正确即可,例如:double a=0.9+0.2;那么只能保证小数点后1位这个精度是正确的,计算机计算这个加法的结果a的值可能是1.100000001,也可能是1.100000002也可能就是1.1,也就是说计算机计算后并不保证0.1以下各位得到的都是正确的,所以直接用==进行比较是不可行的。
我们知道数据在电脑中是以1或0来存储的
下面是64位二进制数:
0100000001000111001101101101001001001000010101110011000100100011
作为Double,是这样分开的:
- 标志(正负数): 0
- 次方数: 10000000100 binary = 1028 次方
- 尾数(精度): 0111001101101101001001001000010101110011000100100011
因此一个正常的数字表达为
(-1)0 x 10111001101101101001001001000010101110011000100100011 (binary) x 21028-1023
which is more simply represented as
1.0111001101101101001001001000010101110011000100100011 (binary) x 25
or
101110.01101101101001001001000010101110011000100100011
所以, 比如象 46.42829231507700882275457843206822872161865234375, 在net中会显示为46.428292315077 或者 46.428292315077009
由上面分析的原因可以看出平时我们写的:
double x = 0.1d;
x其实不等同于0.1,有个能等于0.132323或其他,自然不难得出3.65d+0.05d != 3.7d
但有时候我们这样写程序的时候:
using System;
class Test
{
static void Main(string[] args)
{
float f = Sum (0.1f, 0.2f);
float g = Sum (0.1f, 0.2f);
Console.WriteLine (f==g);
}
static float Sum (float f1, float f2)
{
return f1+f2;
}
}
却发现结果为true,其实在我们编译程序的时候JIT为我们做了部分优化
解决办法
比较两个double数是否相等应看其相减的绝对值是否小于某一数值,此值一般低于两数精确度
例如:Console.WriteLine(Math.Abs(7.88 + 5.00 - 12.88)<0.001);
有兴趣的朋友可以去参考:
http://www.yoda.arachsys.com/csharp/floatingpoint.html