浮点数运算注意事项

时间:2023-01-08 12:48:22

  由于计算机在运算浮点数时,会丢失精度,实际项目中用BigDecimal代替浮点运算。并且由于数据库底层存储浮点数时,如mysql的float及double符合IEEE标准但会受计算机硬件及操作系统影响,而丢失部分精度。mysql的decimal字段,倒是能够解决,它最大表示65位数字,其中小数位最多30。个人觉得最好关于钱这块的字段,数据库存储还是string好,这样可以防止不同数据库的差异。缺点是查询这个字段时,需要转回数值给前台(具体业务需要,只是展示的话不需要);

如:

          double d=29.0*0.01;
          System.out.println("d:"+d);
          
          System.out.println(d*100);

          System.out.println((int)(d*100));


会输出28,原因是d与100运算结果为:28.999999999999996,而最后转int进行了舍入。

用BigDecimal实现上述运算如下:

          BigDecimal a=new BigDecimal("29");
          BigDecimal b=new BigDecimal("0.01");
          BigDecimal c=a.multiply(b);
          
          BigDecimal res=c.multiply(new BigDecimal(100));
          System.out.println("res:"+res);

结果是29


所以实际项目中,会使用BigDecimal来做浮点运算。


最好用BigDecimal,用其中string作为参数的构造函数。如下:

BigDecimal有两个方法用于比较一个是equals一个是compare。

前者会比较小数点位数与值,因此10.00与10.000是不同的数。

而用后者compare比较时,由于该方法只要是值相等就认为相等,因此会返回true。

          BigDecimal a=new BigDecimal("10.00");
          BigDecimal b=new BigDecimal("10.000");
          System.out.println("a==b?"+a.compareTo(b));