電商金額計算的 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開發手冊(嵩山版)》最新發布,速速下載!

以爲不錯,別忘了隨手點贊+轉發哦!

相關文章
相關標籤/搜索