电商金额计算的 4 个坑,千万注意了!

做者:叁滴水

来源:https://blog.csdn.net/qq_3028...java

前言

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

一、多精度计算问题

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

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 个数值想加以后却得出了一个很长的数值。spring

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

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

二、包装类型比对

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。intellij-idea

这是由于Integer的valueOf()方法。ide

//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
}

三、除以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
}

四、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开发手册(嵩山版)》最新发布,速速下载!

以为不错,别忘了随手点赞+转发哦!

相关文章
相关标签/搜索