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);//d=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、尽量避免使用浮点数做比较,如果愣是比较,可以先做精度处理或者先转换成整型再比较。

原文地址:https://www.cnblogs.com/shanfeng1000/p/12398446.html