電商金額計算的 4 個坑,千萬注意了!

作者:叁滴水
來源:https://blog.csdn.net/qq_30285985/
前言
電商項目開發(fā)時肯定少不了金額計算,金額計算時有很多讓人坑人的地方,在此記錄,以免被坑。
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 個數(shù)值想加之后卻得出了一個很長的數(shù)值。
在 java 開發(fā)中可以通過 BigDecimal 進(jìn)行數(shù)值類型的計算,詳細(xì)可到 BigDecimal 工具類。
數(shù)據(jù)庫也是一樣,mysql中有float和double類型,通過sql直接累加數(shù)據(jù)也會有精度缺失的情況。如果要精確的數(shù)值計算,要使用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
}
如上代碼很神奇,同樣是數(shù)值比對100的時候可以通過雙等號返回true。200就返回false。
//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);
}
//Double的valueOf方法
public static Double valueOf(String s) throws NumberFormatException {
return new Double(parseDouble(s));
}
在數(shù)值比對的時候亂的樣子,那我發(fā)現(xiàn)他們都有eq方法,通過這個方法比對可以嗎?
可以的,不管是Integer還是Double都存在一個equas方法,通過這個方法即可進(jìn)行數(shù)值比對。但是這個方法不是很完美。
public static void main (String[] args){
Double i1 = 100d;
System.out.println(i1.equals ("100"));
//false
}
如上所示,因為太多的人都知道字符串類型不能用雙等號進(jìn)行比對,要用eq方法進(jìn)行比對其value。
這樣會讓很多人誤以為Integer和Double類型也是如此,而且在編碼的時候如上這種寫法也沒有報錯,會認(rèn)為都是100肯定會返回true。恰巧這種想法是錯誤的。
public boolean equals(Object obj) {
return (obj instanceof Double)
&& (doubleToLongBits(((Double)obj).value) ==
doubleToLongBits(value));
}
Double的eq方法入?yún)⑹荗bject類型,因此不管傳入什么類型都不會報錯。i1.equals ("100")這種就是雙精度和字符進(jìn)行比對,這兩個永遠(yuǎn)都不可能返回true。正確的寫法應(yīng)該是i1.equals (100d)。
但是盡管多次提醒,但是還是會有不認(rèn)真的開發(fā)小伙伴錯誤,因此,可以使用Double.compareTo方法,這個方法和eq方法類似,但是有編譯的異常,這樣可有效的提醒開發(fā)人員。
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會怎樣?
小學(xué)的時候就講過,進(jìn)行除法運(yùn)算時,除以0是沒有意義的,開發(fā)過程中也是如此, 發(fā)現(xiàn)可能存在除以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轉(zhuǎn)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轉(zhuǎn)換double類型。但是轉(zhuǎn)換之后精度缺失了,只能乖乖的換一種方式轉(zhuǎn)換。
1. 記一次性能優(yōu)化,單臺 4 核 8G 機(jī)器支撐 5 萬 QPS
2. 數(shù)據(jù)庫連接池為什么要用threadlocal呢?不用會怎樣?
最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。
獲取方式:點(diǎn)“在看”,關(guān)注公眾號并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。
文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。
謝謝支持喲 (*^__^*)

