C# double类型精度丢失问题
我们先看一段代码,可以在控制台程序中执行看看结果
{ double d = 500; double d1 = 233.84; double d2 = d - d1; //d2=266.15999999999997 } { double d = 0.4; double d1 = d + d + d; //d1=1.2000000000000002 double d2 = d * 3; //d2=1.2000000000000002 } { double d = 1.2; double d1 = d / 0.4; //d1=2.9999999999999996 }
看到结果,你可能惊讶或者不惊讶,认为计算机计算出现这种精度问题很正常,但是当你做判断时,发现1.2!=0.4*3或者3!=1.2/0.4,你就会懵逼了
bool b1 = 1.2 == 0.4 * 3;//false bool b2 = 3 == 1.2 / 0.4;//false
更有甚者,将计算出来的double类型直接保存在数据库,那保存的也是上面那一堆的小数,后来者看到这个也是奔溃的!
更大的影响是在做金额运算时,我们一般都是精确到分,但是有时会计会发现自己计算出来的数据和我们系统中的对不上,我们的第一感觉也是精度问题,往往会做一个四舍五入,向上取值,向下取值等等操作,那么更大的问题来了,比如向下取值,你会发现1.2/0.4向下取整等于2!
double b = Math.Floor(1.2 / 0.4);//b=2
心中一万只草泥马奔腾而过!
float、double和decimal
float、double和decimal是C#中表示浮点数的类型
类型 | 名称 | bit | 有效数字 | 数值范围 | 是否基础类型 |
float | 单精度浮点数 | 32 | 7 | ±1.5×10E−45 ~ ±3.4×10E38 | 是 |
double | 双精度浮点数 | 64 | 15/16 | ±5.0×10E−324 ~ ±1.7×10E308 | 是 |
decimal | 高精度浮点数 | 128 | 28 | ±1.0×10E−28 ~ ±7.9×10E28 | 否 |
float和double都是基础类型,区别就是表示的数值范围和精度不一样,而decimal是C#作为补充加上来的一个类型,不是基础类型,它拥有更高的精度,但是表示的数值范围却小多了,而且计算速度相对来说要慢一些,但是也足够一般的业务需求了,比如上面的例子,如果把double都换成decimal就不会出现问题了。
float、double和decimal都有精度丢失问题,只不过他们在丢失时的精度条件不一样,而且精度丢失了还不报异常。
个人建议
1、在项目中尽可能的使用decimal,虽然decimal也会出现精度丢失问题,但是一般业务需求是没问题的。
2、当方法返回浮点类型时,或者返回的实体包含有浮点类型,那么在返回时一定要考虑要不要处理精度问题。
3、在对外输出或者存储时,如保存到数据库,一定要根据自己的需求做个精度处理。
4、当基础类型在不同类型之间转换时,尽可能的使用Convert类中的方法,少用强制转换。
5、尽量避免使用浮点数做比较,如果愣是比较,可以先做精度处理或者先转换成整型再比较。