zoukankan      html  css  js  c++  java
  • 电商金额计算的 4 个坑,千万注意了!

    作者:叁滴水

    来源:https://blog.csdn.net/qq_30285985/

    前言

    电商项目开发时肯定少不了金额计算,金额计算时有很多让人坑人的地方,在此记录,以免被坑。

    1、多精度计算问题

    多精度不能直接计算,会存在经度缺失的问题。

    public static void main (String[] args) {
      double num1 = 1;
      double num2 = 31.2;
      double num3 = 323.03;
      System.out.println (num1+num2+num3);
      /**
       * 355.22999999999996
       */
    }
    

    如上代码,3 个数值想加之后却得出了一个很长的数值。

    在 java 开发中可以通过 BigDecimal 进行数值类型的计算,详细可到 BigDecimal 工具类。

    数据库也是一样,mysql中有float和double类型,通过sql直接累加数据也会有精度缺失的情况。如果要精确的数值计算,要使用mysql的decimal类型。

    2、包装类型比对

    public static void main(String[] args) {
         Integer i1 = 100;
         Integer i2 = 100;
         Integer i3 = 200;
         Integer i4 = 200;
         System.out.println(i1==i2); // true
         System.out.println(i3==i4);  // false
    }
    

    如上代码很神奇,同样是数值比对100的时候可以通过双等号返回true。200就返回false。

    这是因为Integer的valueOf()方法。

    //Integer的valueOf方法
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    

    在[-128,128]之间的数,可以通过双等于比对成功,之外的数值就会返回一个new一个新的Integer,因此会返回false。

    Double的比较就简单一点,双等于比对全是false。这是因为Double直接是返回了一个新的Double。
    
    //Double的valueOf方法
    public static Double valueOf(String s) throws NumberFormatException {
        return new Double(parseDouble(s));
    }
    

    在数值比对的时候乱的样子,那我发现他们都有eq方法,通过这个方法比对可以吗?

    可以的,不管是Integer还是Double都存在一个equas方法,通过这个方法即可进行数值比对。但是这个方法不是很完美。

    public static void main (String[] args){
      Double i1 = 100d;
      System.out.println(i1.equals ("100")); 
      //false
    }
    

    如上所示,因为太多的人都知道字符串类型不能用双等号进行比对,要用eq方法进行比对其value。这样会让很多人误以为Integer和Double类型也是如此,而且在编码的时候如上这种写法也没有报错,会认为都是100肯定会返回true。恰巧这种想法是错误的。

    public boolean equals(Object obj) {
        return (obj instanceof Double)
               && (doubleToLongBits(((Double)obj).value) ==
                      doubleToLongBits(value));
    }
    

    Double的eq方法入参是Object类型,因此不管传入什么类型都不会报错。i1.equals ("100")这种就是双精度和字符进行比对,这两个永远都不可能返回true。正确的写法应该是i1.equals (100d)。

    但是尽管多次提醒,但是还是会有不认真的开发小伙伴错误,因此,可以使用Double.compareTo方法,这个方法和eq方法类似,但是有编译的异常,这样可有效的提醒开发人员。

    public static void main (String[] args){
      Double i1 = 100d;
      System.out.println(i1.compareTo (100d)); //0
      System.out.println(i1.compareTo (1d));  //1
    }
    

    3、除以0会怎样?

    小学的时候就讲过,进行除法运算时,除以0是没有意义的,开发过程中也是如此, 发现可能存在除以0的场景要特别注意,程序不会抛出异常,竟然会返回一个字符串!虽然这种场景不多,但是还是需要了解一下。

    1除以0的场景:

    public static void main(String[] args) {
      Double d = 1d;
      double v = d / 0d;
      System.out.println(v);
      //Infinity
    }
    

    0除以0的场景:

    public static void main(String[] args) {
      Double d = 0d;
      double v = d / 0d;
      System.out.println(v);
      //NaN
    }
    

    4、float转double

    public static void main(String[] args) {
    	Float f = 12312.12f;
    	System.out.println(f.doubleValue()); 
    	System.out.println(Double.parseDouble (f.toString ())); 
    	//12312.1201171875
    	//12312.12
    }
    

    Float类中有一个doubleValue方法,返回值是一个double类型,这样会很容易的以为这是float转换double类型。但是转换之后精度缺失了,只能乖乖的换一种方式转换。

    近期热文推荐:

    1.600+ 道 Java面试题及答案整理(2021最新版)

    2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香!

    3.阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

    4.Spring Cloud 2020.0.0 正式发布,全新颠覆性版本!

    5.《Java开发手册(嵩山版)》最新发布,速速下载!

    觉得不错,别忘了随手点赞+转发哦!

  • 相关阅读:
    poj 2528 Mayor's posters (线段树+离散化)
    poj 1201 Intervals (差分约束)
    hdu 4109 Instrction Arrangement (差分约束)
    poj 1195 Mobile phones (二维 树状数组)
    poj 2983 Is the Information Reliable? (差分约束)
    树状数组 讲解
    poj 2828 Buy Tickets (线段树)
    hdu 1166 敌兵布阵 (树状数组)
    Ubuntu网络配置
    Button控制窗体变量(开关控制灯的状态)
  • 原文地址:https://www.cnblogs.com/javastack/p/14797278.html
Copyright © 2011-2022 走看看