欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java優(yōu)雅的處理金錢問題(BigDecimal)

 更新時間:2023年06月07日 10:50:17   作者:xie_zhr  
本文主要介紹了Java優(yōu)雅的處理金錢問題(BigDecimal),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

有多少小伙伴是被標(biāo)題 吸引進來的呢,我可不是標(biāo)題黨,今天的文章呢確實跟”金錢“有關(guān)系。

但是我們說的不是過度追求金錢而掉入陷阱,而是要說一說在Java程序中,各種跟金錢運算有關(guān)的陷阱。

日常工作中我們經(jīng)常會涉及到各種金額這樣浮點數(shù)的運算。

一旦涉及到金額的運算就必須慎之又慎,一旦有精度丟失,或者其他運算錯誤就可能造成無可挽回的損失。

一 、 存在的陷阱

這一小節(jié)我們先將陷阱列出來,下一小節(jié)分別給出解決方案。

我們先來看看到底有哪些坑等著我們?nèi)ゲ?/p>

1.1 浮點運算精度丟失陷阱

public class BigDecimalDemo {
    public static void main(String[] args) {
        float a = 1.0f - 0.9f;
        float b = 0.9f - 0.8f;
        System.out.println("a= "+a);
        System.out.println("b= "+b);
    }
}
//輸出結(jié)果
a= 0.100000024
b= 0.099999964

1.2 浮點數(shù)等值判斷陷阱

① 基本類型與包裝類型判斷浮點數(shù)是否相等

public class BigDecimalDemo {
    public static void main(String[] args) {
        float a = 1.0F - 0.9F;
        float b = 0.9F - 0.8F;
        System.out.println("通過==判斷a與b是否相等:"+ (a == b));
        Float x = Float.valueOf(a);
        Float y = Float.valueOf(b);
        System.out.println("通過equals方法判斷x與y是否相等:"+ x.equals(y));
    }
}
//輸出結(jié)果
通過==判斷a與b是否相等false
通過equals方法判斷x y是否相等false

BigDecimal類通過equals 方法判斷是否相等

public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("2");
        BigDecimal b = new BigDecimal("2.0");
        System.out.println(a.equals(b));
    }
}
//輸出結(jié)果
false

1.3 BigDecimal 構(gòu)造方法中的陷阱

public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal(0.1f);
        System.out.println("a= "+ a);
    }
}
//輸出結(jié)果
a= 0.100000001490116119384765625

1.4 BigDecimal 除法陷阱

如果兩數(shù)相除無法除盡,拋出 ArithmeticException 異常

public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("0.2");
        BigDecimal b = new BigDecimal("0.3");
        System.out.println(a.divide(b));
    }
}
//輸出結(jié)果
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
	at java.math.BigDecimal.divide(BigDecimal.java:1693)
	at com.xiezhr.BigDecimalDemo.main(BigDecimalDemo.java:17)

二、避免陷阱

2.1 浮點數(shù)運算避坑

① 我們先來看看為什么浮點數(shù)(也就是floatdouble 關(guān)鍵字定義的數(shù)) 運算的時候精度會丟失?

我們直到計算機是以二進制的方式進行數(shù)據(jù)存儲的,在表示一個數(shù)字時,寬度時有限的。

十進制的 0.1 轉(zhuǎn)為二進制,得到一個無限循環(huán)小數(shù):0.00011… (看不懂的自覺點回去翻一翻大一的《計算機基礎(chǔ)》課本)

無限循環(huán)的小數(shù)存儲在計算機時,只能被截斷,所以就會導(dǎo)致小數(shù)精度發(fā)生損失的情況。

這就是為什么浮點數(shù)沒有辦法用二進制精確表示。

我們怎么來填1.1 中的坑呢?

public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("1.0");
        BigDecimal b = new BigDecimal("0.9");
        BigDecimal c = new BigDecimal("0.9");
        BigDecimal d = new BigDecimal("0.8");
        System.out.println("a-b = "+a.subtract(b));
        System.out.println("c-d = "+c.subtract(d));
    }
}
//輸出結(jié)果
a-b = 0.1
c-d = 0.1

2.2 浮點數(shù)等值判斷避坑

日常開發(fā)中肯定時免不了比較兩個浮點數(shù)大小的,這里呢就把1.2中的坑給填上

① 指定一個誤差范圍,若兩個浮點數(shù)的差值在誤差范圍內(nèi),則認(rèn)為兩個浮點數(shù)時相等的

public class BigDecimalDemo {
    public static void main(String[] args) {
        float a = 1.0F - 0.9F;
        float b = 0.9F - 0.8F;
        //表示10的-6次方
        float diff = 1e-6f;
        if (Math.abs(a - b )< diff) {
            System.out.println("a與b相等");
        }
    }
}
//輸出結(jié)果
a與b相等

② 使用BigDecimal定義值,再進行運算操作,最后使用compareTo 方法比較

public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("1.0");
        BigDecimal b = new BigDecimal("0.9");
        BigDecimal c = new BigDecimal("0.8");
        BigDecimal x = a.subtract(b);
        BigDecimal y = b.subtract(c);
        if(x.compareTo(y)==0){
            System.out.println("x與y相等");
        }
    }
}
//輸出結(jié)果
x與y相等

2.3 BigDecimal 構(gòu)造方法避坑

陷阱的產(chǎn)生:

double的構(gòu)造方法的結(jié)果有一定的不可預(yù)知性,

newBigDecimal(1.0)所創(chuàng)建的實際上等于0.1000000000000000055511151231257827021181583404541015625。

因為0.1無法準(zhǔn)確地表示為 double,傳入到構(gòu)造方法的值不會正好等于 0.1

String 構(gòu)造方法是完全可預(yù)知的

? 寫入 newBigDecimal("0.1") 將創(chuàng)建一個 BigDecimal,它正好等于預(yù)期的 0.1

這里來填1.3中的坑,這里有兩種方案

《阿里巴巴Java開發(fā)手冊》1.4 OOP 規(guī)約中提到

? 【強制】 禁止使用構(gòu)造方法BigDecimal(double)的方式把double值 轉(zhuǎn)換為BigDecimal 對象

說明: BigDecimal(double) 存在精度損失風(fēng)險,在精確計算或值比較的場景中,可能會導(dǎo)致業(yè)務(wù)邏輯出現(xiàn)異常。

如:BigDecimal g = new BigDecimal(0.1f); 實際存儲值為:0.100000001490116119384765625

正例: 優(yōu)先推薦入?yún)?code>String 的構(gòu)造方法,或使用BigDecimalvalueOf 方法。

此方法內(nèi)部其實執(zhí)行了DoubletoString, 而DoubletoStringdouble 的實際能表達的精度對尾數(shù)進行了截斷。

BigDecimal good1 = new BigDecimal("0.1");
BigDecimal good2 = BigDecimal.valueOf(0.1);

①將BigDecimal(double) ==》BigDecimal(String)

public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal(Double.toString(0.1));
        System.out.println("a=" + a);
    }
}
//輸出結(jié)果
a=0.1

②使用BigDecimal類的valueOf 方法

public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal a =  BigDecimal.valueOf(0.1);
        System.out.println("a=" + a);
    }
}
//輸出結(jié)果
a=0.1

2.4 BigDecimal 除法避坑

我們使用帶有3個參數(shù)的divide 方法來填1.4中的坑

public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("0.2");
        BigDecimal b = new BigDecimal("0.3");
		//這里就簡單的看作四舍五入就行了
        System.out.println("a除以b等于:"+ a.divide(b, 2, RoundingMode.HALF_UP));
    }
}
//輸出結(jié)果
a除以b等于:0.67

三、BigDecimal 常用方法

常用構(gòu)造方法

構(gòu)造方法

常用方法

常用方法

3.1 加法運算 add

public class BigDecimalDemo {
    public static void main(String[] args) {
       BigDecimal a = new BigDecimal(Double.toString(0.1));
       BigDecimal b = BigDecimal.valueOf(0.2);
        System.out.println("a + b ="+a.add(b));
    }
}
//輸出結(jié)果
a + b =0.3

3.2 減法運算 subtract

public class BigDecimalDemo {
    public static void main(String[] args) {
       BigDecimal a = new BigDecimal(Double.toString(3.5));
       BigDecimal b = BigDecimal.valueOf(2.1);
        System.out.println("a - b ="+a.subtract(b));
    }
}
//輸出結(jié)果
a - b =1.4

3.3 乘法運算 multiply

public class BigDecimalDemo {
    public static void main(String[] args) {
       BigDecimal a = new BigDecimal(Double.toString(2.5));
       BigDecimal b = BigDecimal.valueOf(3.26);
        System.out.println("a * b ="+a.multiply(b));
    }
}
//輸出結(jié)果
a * b =8.150

3.4 除法運算 divide

BigDecimal除法可能出現(xiàn)不能整除的情況,比如 1.2/1.3,

這時會報錯java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

這個之前也說過,這里呢再詳細(xì)說說divide 方法

BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) 
  • divisor : 表示除數(shù)
  • scale: 表示小數(shù)點后保留位數(shù)
  • roundingMode: 表示舍入模式。roundingMode是一個枚舉類,有八種舍入模式

我們以0.333 和-0.333保留2位小數(shù)為例,采用不同模式后得結(jié)果為

–模式–模式說明圖形說明
UP遠(yuǎn)離0的舍入模式【0.333–>0.34 -0.333 -->-0.34

遠(yuǎn)離0

DOWN接近0的舍入模式【0.333–>0.33 -0.333 -->-0.33近0模式
CEILINGCEILING英文是天花板的意思,可以理解為向”大“舍入【0.333–>0.34 -0.333 -->-0.33image-20230605230527632
FLOORFLOOR有地板的意思,可以理解為向”小“舍入【0.333–>0.33 -0.333 -->-0.34image-20230605230636060
HALF_UP向“最接近的”數(shù)字舍入,如果與兩個相鄰數(shù)字的距離相等,則為向上舍入的舍入其實就是四舍五入>=0.5 入,<0.5的舍去
HALF_DOWN向“最接近的”數(shù)字舍入,如果與兩個相鄰數(shù)字的距離相等,則為上舍入的舍入,其實就是五舍六入>0.5 的入,<=0.5 的舍去
HALF_EVEN向“最接近的”數(shù)字舍入,如果與兩個相鄰數(shù)字的距離相等,則向相鄰的偶數(shù)舍入【0.135–>0.14 0.125–>0.12
UNNECESSARY斷言請求的操作具有精確的結(jié)果,因此不需要舍入
public class BigDecimalDemo {
    public static void main(String[] args) {
            BigDecimal numA = new BigDecimal("1");
            BigDecimal numB = new BigDecimal("-1");
            BigDecimal numC = new BigDecimal("3");
            // 保留兩位小數(shù),舍入模式為UP
            System.out.println("1/3保留兩位小數(shù)(UP) = " + numA.divide(numC, 2, RoundingMode.UP));
            System.out.println("-1/3保留兩位小數(shù)(UP) = " + numB.divide(numC, 2, RoundingMode.UP));
            // 保留兩位小數(shù),舍入模式為DOWN
            System.out.println("1/3保留兩位小數(shù)(DOWN) = " + numA.divide(numC, 2, RoundingMode.DOWN));
            System.out.println("-1/3保留兩位小數(shù)(DOWN) = " + numB.divide(numC, 2, RoundingMode.DOWN));
            // 保留兩位小數(shù),舍入模式為CEILING
            System.out.println("1/3保留兩位小數(shù)(CEILING) = " + numA.divide(numC, 2, RoundingMode.CEILING));
            System.out.println("-1/3保留兩位小數(shù)(CEILING) = " + numB.divide(numC, 2, RoundingMode.CEILING));
            // 保留兩位小數(shù),舍入模式為FLOOR
            System.out.println("1/3保留兩位小數(shù)(FLOOR) = " + numA.divide(numC, 2, RoundingMode.FLOOR));
            System.out.println("-1/3保留兩位小數(shù)(FLOOR) = " + numB.divide(numC, 2, RoundingMode.FLOOR));
            BigDecimal numD = new BigDecimal("1");
            BigDecimal numE = new BigDecimal("-1");
            BigDecimal numF = new BigDecimal("8");
            // 保留兩位小數(shù),舍入模式為HALF_UP
            System.out.println("1/8(=0.125)保留兩位小數(shù)(HALF_UP) = " + numD.divide(numF, 2, RoundingMode.HALF_UP));
            System.out.println("-1/8(=0.125)保留兩位小數(shù)(HALF_UP) = " + numE.divide(numF, 2, RoundingMode.HALF_UP));
            // 保留兩位小數(shù),舍入模式為HALF_DOWN
            System.out.println("1/8(=0.125)保留兩位小數(shù)(HALF_DOWN) = " + numD.divide(numF, 2, RoundingMode.HALF_DOWN));
            System.out.println("-1/8(=0.125)保留兩位小數(shù)(HALF_DOWN) = " + numE.divide(numF, 2, RoundingMode.HALF_DOWN));
            // 保留兩位小數(shù),舍入模式為HALF_EVEN
            System.out.println("0.54/4(=0.135)保留兩位小數(shù)(HALF_EVEN) = " + new BigDecimal("0.54").divide(new BigDecimal("4"), 2, RoundingMode.HALF_EVEN));
            System.out.println("1/8(=0.125)保留兩位小數(shù)(HALF_EVEN) = " + numE.divide(numF, 2, RoundingMode.HALF_EVEN));
            //UNNECESSARY,會報異常
            System.out.println("1/8(=0.125) = " + numE.divide(numF,  RoundingMode.UNNECESSARY));
        }
}
//輸出結(jié)果
1/3保留兩位小數(shù)(UP) = 0.34
-1/3保留兩位小數(shù)(UP) = -0.34
1/3保留兩位小數(shù)(DOWN) = 0.33
-1/3保留兩位小數(shù)(DOWN) = -0.33
1/3保留兩位小數(shù)(CEILING) = 0.34
-1/3保留兩位小數(shù)(CEILING) = -0.33
1/3保留兩位小數(shù)(FLOOR) = 0.33
-1/3保留兩位小數(shù)(FLOOR) = -0.34
1/8(=0.125)保留兩位小數(shù)(HALF_UP) = 0.13
-1/8(=0.125)保留兩位小數(shù)(HALF_UP) = -0.13
1/8(=0.125)保留兩位小數(shù)(HALF_DOWN) = 0.12
-1/8(=0.125)保留兩位小數(shù)(HALF_DOWN) = -0.12
0.54/4(=0.135)保留兩位小數(shù)(HALF_EVEN) = 0.14
1/8(=0.125)保留兩位小數(shù)(HALF_EVEN) = -0.12
Exception in thread "main" java.lang.ArithmeticException: Rounding necessary

3.5 值轉(zhuǎn)換

public class BigDecimalDemo {
    public static void main(String[] args) {
            BigDecimal a = new BigDecimal(Double.toString(2.3));
            BigDecimal b = new BigDecimal(10200000);
            System.out.println("BigDecimal轉(zhuǎn)字符串:"+a.toString());
            System.out.println("BigDecimal轉(zhuǎn)double:"+a.doubleValue());
            System.out.println("BigDecimal轉(zhuǎn)float:"+a.floatValue());
            System.out.println("BigDecimal轉(zhuǎn)長整型:"+b.longValue());
            System.out.println("BigDecimal轉(zhuǎn)int:"+b.intValue());
    }
}
//輸出結(jié)果
BigDecimal轉(zhuǎn)字符串:2.3
BigDecimal轉(zhuǎn)double:2.3
BigDecimal轉(zhuǎn)float:2.3
BigDecimal轉(zhuǎn)長整型:10200000
BigDecimal轉(zhuǎn)int:10200000

3.6 絕對值 abs

public class BigDecimalDemo {
    public static void main(String[] args) {
            BigDecimal a = new BigDecimal(Double.toString(2.35));
            BigDecimal b = BigDecimal.valueOf(-2.35);
            System.out.println("a的絕對值是:" + a.abs());
            System.out.println("b的絕對值是:" + b.abs());
    }
}
//輸出結(jié)果
a的絕對值是:2.35
b的絕對值是:2.35

3.7 等值比較

《阿里巴巴Java開發(fā)手冊》第一章 1.4 OOP規(guī)約 中提到

?**【強制】** 浮點數(shù)之間的等值判斷,基本數(shù)據(jù)類型不能用==進行比較,包裝數(shù)據(jù)類型不能用equals方法判斷。

說明: 浮點數(shù)采用“尾數(shù)+階碼”的編碼方式,類似于科學(xué)計數(shù)法的“有效數(shù)字+指數(shù)“ 的表示方式。

二級制無法精確表示大部分十進制小數(shù),具體原理參考《碼出高效,Java開發(fā)手冊》

反例:
    float a = 1.0f - 0.9f;
    float b = 0.9f - 0.8 f;
	if(a==b){
        //預(yù)期進入此代碼塊,執(zhí)行其他業(yè)務(wù)邏輯
        //但事實上a==b 的結(jié)果為false
    }
	Float x = Float.valueOf(a);
	Float y = Float.valueOf(b);
	if(x.equals(y)){
        // 預(yù)期進入此代碼塊,執(zhí)行其他業(yè)務(wù)邏輯
        //但事實上x.equals(y)的結(jié)果為false
    }
正例:
    1)指定一個誤差范圍,若兩個浮點數(shù)的差值在此范圍之內(nèi),則認(rèn)為是相等的。
    float a = 1.0f - 0.9f;
    float b = 0.9f - 0.8f;
	//10的-6次方
	float diff = 1e-6f;
	if(Math.abs(a-b)<diff){
        System.out.println("true");
    }
	2)使用BigDecimal定義值,再進行浮點數(shù)的運算操作。
    BigDecimal a = BigDecimal("0.1");
    BigDecimal b = BigDecimal("0.9");
    BigDecimal c = BigDecimal("0.8");
	BigDecimal x = a.subtract(b);
	BigDecimal y = b.subtract(c);
	/**
	*BigDecimal的等值比較應(yīng)使用compareTo()方法,而不是equals() 方法。
	*說明:equals()方法會比較值和精度(1.0 與1.00 返回結(jié)果為false),
	*而compareTo()則會忽略精度。
	**/
	if (x.compareTo(y)==0){
        System.out.println("true");
    }

等值比較compareTo(BigDecimal val) 方法

a.compareTo(b)

  • -1:表示a小于b
  • 0:表示a等于b
  • 1:表示a大于b
public class BigDecimalDemo {
    public static void main(String[] args) {
            BigDecimal a = new BigDecimal("0.5");
            BigDecimal b = new BigDecimal("0.8");
            BigDecimal c = new BigDecimal("0.3");
            BigDecimal d = new BigDecimal("0.5");
            System.out.println("a與b比較結(jié)果:"+a.compareTo(b));
            System.out.println("a與c比較結(jié)果:"+a.compareTo(c));
            System.out.println("a與d比較結(jié)果:"+a.compareTo(d));
    }
}
//輸出結(jié)果
a與b比較結(jié)果:-1
a與c比較結(jié)果:1
a與d比較結(jié)果:0

四、BigDecimal格式化

NumberFormat類的format()方法可以使用BigDecimal對象作為參數(shù),

可以對超出16位有效數(shù)字的貨幣值,百分值,以及一般數(shù)值進行格式化控制

public class BigDecimalDemo {
    public static void main(String[] args) {
            NumberFormat money = NumberFormat.getCurrencyInstance(); //建立貨幣格式化引用
            NumberFormat percent = NumberFormat.getPercentInstance();  //建立百分比格式化引用
            percent.setMaximumFractionDigits(3); //百分比小數(shù)點最多3位
            BigDecimal loanAmount = new BigDecimal("15000.48"); //貸款金額
            BigDecimal interestRate = new BigDecimal("0.008"); //利率
            BigDecimal interest = loanAmount.multiply(interestRate); //相乘
            System.out.println("貸款金額:" + money.format(loanAmount));
            System.out.println("利率:" + percent.format(interestRate));
            System.out.println("利息:" + money.format(interest));
    }
}
//輸出結(jié)果
貸款金額:¥15,000.48
利率:0.8%
利息:¥120.00

五、BigDecimal工具類

為了更加方便的使用BigDecimal 我們可以將其常用方法封裝成工具類

package com.xiezhr.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
 * 簡化BigDecimal計算的小工具類
 */
public class BigDecimalUtil {
    /**
     * 默認(rèn)除法運算精度
     */
    private static final int DEF_DIV_SCALE = 10;
    private BigDecimalUtil() {
    }
    /**
     * 提供精確的加法運算。
     *
     * @param v1 被加數(shù)
     * @param v2 加數(shù)
     * @return 兩個參數(shù)的和
     */
    public static double add(double v1, double v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.add(b2).doubleValue();
    }
    /**
     * 提供精確的減法運算。
     *
     * @param v1 被減數(shù)
     * @param v2 減數(shù)
     * @return 兩個參數(shù)的差
     */
    public static double subtract(double v1, double v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.subtract(b2).doubleValue();
    }
    /**
     * 提供精確的乘法運算。
     *
     * @param v1 被乘數(shù)
     * @param v2 乘數(shù)
     * @return 兩個參數(shù)的積
     */
    public static double multiply(double v1, double v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.multiply(b2).doubleValue();
    }
    /**
     * 提供(相對)精確的除法運算,當(dāng)發(fā)生除不盡的情況時,精確到
     * 小數(shù)點以后10位,以后的數(shù)字四舍五入。
     *
     * @param v1 被除數(shù)
     * @param v2 除數(shù)
     * @return 兩個參數(shù)的商
     */
    public static double divide(double v1, double v2) {
        return divide(v1, v2, DEF_DIV_SCALE);
    }
    /**
     * 提供(相對)精確的除法運算。當(dāng)發(fā)生除不盡的情況時,由scale參數(shù)指
     * 定精度,以后的數(shù)字四舍五入。
     *
     * @param v1    被除數(shù)
     * @param v2    除數(shù)
     * @param scale 表示表示需要精確到小數(shù)點以后幾位。
     * @return 兩個參數(shù)的商
     */
    public static double divide(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
    }
    /**
     * 提供精確的小數(shù)位四舍五入處理。
     *
     * @param v     需要四舍五入的數(shù)字
     * @param scale 小數(shù)點后保留幾位
     * @return 四舍五入后的結(jié)果
     */
    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b = BigDecimal.valueOf(v);
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
    }
    /**
     * 提供精確的類型轉(zhuǎn)換(Float)
     *
     * @param v 需要被轉(zhuǎn)換的數(shù)字
     * @return 返回轉(zhuǎn)換結(jié)果
     */
    public static float convertToFloat(double v) {
        BigDecimal b = new BigDecimal(v);
        return b.floatValue();
    }
    /**
     * 提供精確的類型轉(zhuǎn)換(Int)不進行四舍五入
     *
     * @param v 需要被轉(zhuǎn)換的數(shù)字
     * @return 返回轉(zhuǎn)換結(jié)果
     */
    public static int convertsToInt(double v) {
        BigDecimal b = new BigDecimal(v);
        return b.intValue();
    }
    /**
     * 提供精確的類型轉(zhuǎn)換(Long)
     *
     * @param v 需要被轉(zhuǎn)換的數(shù)字
     * @return 返回轉(zhuǎn)換結(jié)果
     */
    public static long convertsToLong(double v) {
        BigDecimal b = new BigDecimal(v);
        return b.longValue();
    }
    /**
     * 返回兩個數(shù)中大的一個值
     *
     * @param v1 需要被對比的第一個數(shù)
     * @param v2 需要被對比的第二個數(shù)
     * @return 返回兩個數(shù)中大的一個值
     */
    public static double returnMax(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.max(b2).doubleValue();
    }
    /**
     * 返回兩個數(shù)中小的一個值
     *
     * @param v1 需要被對比的第一個數(shù)
     * @param v2 需要被對比的第二個數(shù)
     * @return 返回兩個數(shù)中小的一個值
     */
    public static double returnMin(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.min(b2).doubleValue();
    }
    /**
     * 精確對比兩個數(shù)字
     *
     * @param v1 需要被對比的第一個數(shù)
     * @param v2 需要被對比的第二個數(shù)
     * @return 如果兩個數(shù)一樣則返回0,如果第一個數(shù)比第二個數(shù)大則返回1,反之返回-1
     */
    public static int compareTo(double v1, double v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.compareTo(b2);
    }
}

六、避坑小結(jié)

  • 商業(yè)計算使用BigDecimal
  • 盡量使用參數(shù)類型為String的構(gòu)造函數(shù)
  • BigDecimal都是不可變的,在進行每一步運算時,都會產(chǎn)生一個新的對象,所以在做加減乘除運算時千萬要保存操作后的值

到此這篇關(guān)于Java優(yōu)雅的處理金錢問題(BigDecimal)的文章就介紹到這了,更多相關(guān)Java 金錢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論