Java中BigInteger與BigDecimal類用法總結(jié)
一. BigInteger類
1. 簡介
在之前給大家講解8種基本類型時(shí)就說過,不同的數(shù)據(jù)類型,有不同的取值范圍,我們再通過下表回顧一下:
類型 | 所占字節(jié)(byte) | 所占位數(shù)(bit) | 取值范圍 |
---|---|---|---|
byte | 1 | 8 | -2^7 ~ 2^7-1 |
short | 2 | 16 | -2^15 ~2^15-1 |
int | 4 | 32 | -2^31 ~ 2^31-1 |
long | 8 | 64 | -2^63 ~ 2^63-1 |
char | 2字節(jié) | 16位 | 0~65535 |
float | 4字節(jié) | 32位 | ±3.4E+38 |
double | 8字節(jié) | 64位 | ±1.7E+308 |
boolean | 4字節(jié) | 32位 | true\false |
從上表中我們可以看到,整型的最大取值范圍是-2^63 ~ 2^63-1,浮點(diǎn)型的最大取值范圍是±1.7E+308。但是不管這個(gè)范圍有多大,有些小伙伴就想杠一下,如果我就要存一個(gè)比Integer或Long更大的數(shù)字,怎么辦?
針對這種大整數(shù)的需求,我們可以使用BigInteger,它的數(shù)字范圍比 Integer類型的數(shù)字范圍要大得多,而且BigInteger支持任意精度的整數(shù)。也就是說在運(yùn)算中,BigInteger類型可以準(zhǔn)確地表示任何大小的整數(shù)值。BigInteger和Integer、Long一樣都是Number的子類,屬于不可變類。它自身帶有一些可以進(jìn)行運(yùn)算的方法,包括基本的加、減、乘、除操作,還有很多較為高級的操作,像求絕對值、相反數(shù)、最大公約數(shù)及判斷是否為質(zhì)數(shù)等,所以BigInteger用起來是比較方便的。
2. 使用方法
2.1 常用API方法
如果我們要使用BigInteger類,首先要?jiǎng)?chuàng)建一個(gè)BigInteger對象。BigInteger類提供了多個(gè)構(gòu)造方法,其中最直接的一個(gè)是以字符串作為參數(shù)的構(gòu)造方法,即BigInteger(String val)。在創(chuàng)建BigInteger對象之后,我們就可以調(diào)用BigInteger類提供的方法,進(jìn)行各種數(shù)學(xué)運(yùn)算了,這些常用的API方法如下:
方法名稱 | 說明 |
---|---|
add(BigInteger val) | 做加法運(yùn)算 |
subtract(BigInteger val) | 做減法運(yùn)算 |
multiply(BigInteger val) | 做乘法運(yùn)算 |
divide(BigInteger val) | 做除法運(yùn)算 |
remainder(BigInteger val) | 做取余數(shù)運(yùn)算 |
divideAndRemainder(BigInteger val) | 做除法運(yùn)算,返回?cái)?shù)組的第一個(gè)值為商,第二個(gè)值為余數(shù) |
pow(int exponent) | 做參數(shù)的 exponent 次方運(yùn)算 |
negate() | 取相反數(shù) |
shiftLeft(int n) | 將數(shù)字左移 n 位,如果 n 為負(fù)數(shù),則做右移操作 |
shiftRight(int n) | 將數(shù)字右移 n 位,如果 n 為負(fù)數(shù),則做左移操作 |
and(BigInteger val) | 做與運(yùn)算 |
or(BigInteger val) | 做或運(yùn)算 |
compareTo(BigInteger val) | 做數(shù)字的比較運(yùn)算 |
equals(Object obj) | 當(dāng)參數(shù) obj 是 Biglnteger 類型的數(shù)字并且數(shù)值相等時(shí)返回 true, 其他返回 false |
min(BigInteger val) | 返回較小的數(shù)值 |
max(BigInteger val) | 返回較大的數(shù)值 |
2.2 基本案例
我們先來通過一個(gè)案例,來驗(yàn)證一下BigInteger中的數(shù)字到底有多大。
public static void main(String[] args) { //創(chuàng)建一個(gè)BigInteger對象 BigInteger bi = new BigInteger("1234567890"); //計(jì)算1234567890的15次方, //結(jié)果=23589821655914838120947036369147203948318169938519404175968425823418008249115809912616071588527110255905622789563711716349000000000000000 System.out.println(bi.pow(15)); }
我們會發(fā)現(xiàn),BigInteger可以表示一個(gè)非常大的數(shù)字,比Integer、Long的范圍都要大。
2.3 類型轉(zhuǎn)換
在上面說過,BigInteger其實(shí)是Number的子類,我們知道,Number中定義了幾個(gè)負(fù)責(zé)類型轉(zhuǎn)換的方法,比如:
- 轉(zhuǎn)換為 byte : byteValue()
- 轉(zhuǎn)換為 short : shortValue()
- 轉(zhuǎn)換為 int : intValue()
- 轉(zhuǎn)換為 long : longValue()
- 轉(zhuǎn)換為 float : floatValue()
- 轉(zhuǎn)換為 double : doubleValue()
我們利用上述幾個(gè)方法,就可以把BigInteger轉(zhuǎn)換成基本類型。但是大家要注意,如果BigInteger表示的范圍超過了基本類型的范圍,在轉(zhuǎn)換時(shí)會丟失高位信息,也就是說,結(jié)果不一定準(zhǔn)確。所以如果我們需要準(zhǔn)確地轉(zhuǎn)換成基本類型,可以使用intValueExact()、longValueExact()這樣的方法。不過這種方法在轉(zhuǎn)換時(shí)如果超出了基本類型的范圍,會直接拋出ArithmeticException異常。我們來驗(yàn)證一下吧。
public static void main(String[] args) { //BigInteger轉(zhuǎn)基本類型 BigInteger bi02 = new BigInteger("123456789000"); //123456789000 System.out.println("轉(zhuǎn)為int類型="+bi02.intValue()); System.out.println("轉(zhuǎn)為float類型="+bi02.floatValue()); System.out.println("轉(zhuǎn)為long類型="+bi02.longValue()); //將123456789000乘以123456789000,然后將結(jié)果轉(zhuǎn)為long類型 //java.lang.ArithmeticException: BigInteger out of long range System.out.println("得到精確結(jié)果="+bi02.multiply(bi02).longValueExact()); }
但是如果BigInteger的值超過了float的最大范圍(3.4x1038),結(jié)果并不會出現(xiàn)ArithmeticException異常,而是會出現(xiàn)Infinity,如下所示:
//計(jì)算999999的99次方,并得到該結(jié)果的float值 BigInteger bi03 = new BigInteger("999999").pow(99); float f = bi03.floatValue(); System.out.println("結(jié)果="+f);
2.4 其他用法
接下來我們再來看看其他的API方法都有哪些作用。
import java.math.BigInteger; import java.util.Scanner; /** * @author */ public class Demo10 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("請輸入一個(gè)整數(shù):"); // 保存用戶輸入的數(shù)字 int num = scanner.nextInt(); // 使用輸入的數(shù)字創(chuàng)建BigInteger對象 BigInteger bi = new BigInteger(num + ""); // 計(jì)算大數(shù)字加上99的結(jié)果 System.out.println("加法的結(jié)果:" + bi.add(new BigInteger("99"))); // 計(jì)算大數(shù)字減去25的結(jié)果 System.out.println("減法的結(jié)果:" + bi.subtract(new BigInteger("25"))); // 計(jì)算大數(shù)字乘以3的結(jié)果 System.out.println("乘法的結(jié)果:" + bi.multiply(new BigInteger("3"))); // 計(jì)算大數(shù)字除以2的結(jié)果 System.out.println("除法的結(jié)果:" + bi.divide(new BigInteger("2"))); // 計(jì)算大數(shù)字除以3的商 System.out.println("取商的結(jié)果:" + bi.divideAndRemainder(new BigInteger("3"))[0]); // 計(jì)算大數(shù)字除以3的余數(shù) System.out.println("取余的結(jié)果:" + bi.divideAndRemainder(new BigInteger("3"))[1]); // 計(jì)算大數(shù)字的4次方 System.out.println("4次方的結(jié)果:" + bi.pow(4)); // 計(jì)算大數(shù)字的相反數(shù) System.out.println("取反的結(jié)果:" + bi.negate()); } }
在上述案例中,我們將用戶輸入的數(shù)字作為 BigInteger 對象的參數(shù),然后調(diào)用該對象的各種方法,實(shí)現(xiàn)了加、減、乘、除等運(yùn)算,并輸出了最終的結(jié)果。
二. BigDecimal類
1. 簡介
雖然都是用于大數(shù)字運(yùn)算的類,但BigDecimal加入了小數(shù)的概念,所以是可以操作小數(shù)的。而float 和 double類型,只能用來進(jìn)行科學(xué)計(jì)算或工程計(jì)算,并不適用于精度要求較高的商業(yè)計(jì)算(如貨幣計(jì)算),所以要用到支持任何精度的BigDecimal類。該類中提供了一系列對應(yīng)的方法,可以用來做超大浮點(diǎn)數(shù)的運(yùn)算,像加、減、乘和除等。在所有運(yùn)算中,除法運(yùn)算是最復(fù)雜的,因?yàn)榇嬖诔槐M的情況,需要我們考慮末位小數(shù)的處理方式。
2. 使用方法
2.1 常用構(gòu)造方法
以下是BigDecimal類的常用構(gòu)造方法:
- BigDecimal(double val):實(shí)例化對象時(shí)可以將雙精度型轉(zhuǎn)換為BigDecimal類型;
- BigDecimal(String val):實(shí)例化對象時(shí)可以將字符串形式轉(zhuǎn)換為BigDecimal類型。
2.2 常用API方法
除了構(gòu)造方法之外,BigDecimal還提供了一些常用的API方法供我們進(jìn)行數(shù)學(xué)運(yùn)算。這些方法與BigInteger的方法類型,很多方法名稱和用法也都與之一致,所以這里就不再一一列出了,接下來我就直接通過一個(gè)案例給大家演示這些方法如何使用。
import java.math.BigDecimal; /** * @author */ public class Demo11 { public static void main(String[] args) { BigDecimal bd = new BigDecimal("1000.05800"); // 計(jì)算大數(shù)字加上99的結(jié)果 System.out.println("加法的結(jié)果:" + bd.add(new BigDecimal("99"))); // 計(jì)算大數(shù)字減去25的結(jié)果 System.out.println("減法的結(jié)果:" + bd.subtract(new BigDecimal("25"))); // 計(jì)算大數(shù)字乘以1000的結(jié)果 System.out.println("乘法的結(jié)果:" + bd.multiply(new BigDecimal(1000))); //獲取小數(shù)的位數(shù),5 System.out.println(bd.scale()); //去掉BigDecimal末尾的0,返回一個(gè)與原有BigDecimal相等的新對象 BigDecimal bd2 = bd.stripTrailingZeros(); System.out.println(bd2.scale()); } }
在上述代碼中,stripTrailingZeros()方法用于去掉BigDecimal末尾的0,并返回一個(gè)與原有BigDecimal相等的新對象。而scale()方法用于獲取一個(gè)數(shù)字后面0的個(gè)數(shù),如果返回的是負(fù)數(shù),比如-2,則表示該數(shù)是一個(gè)整數(shù),且末尾有2個(gè)0。
2.3 divide()除法
BigDecimal進(jìn)行加、減、乘時(shí),數(shù)字的精度不會丟失,但是進(jìn)行除法運(yùn)算時(shí),有可能會出現(xiàn)無法除盡的情況,此時(shí)必須指定精度以及如何進(jìn)行截?cái)?。BigDecimal給我們提供了divide()和divideAndRemainder()兩個(gè)方法可以進(jìn)行除法運(yùn)算。
其中,divide()方法有3個(gè)參數(shù)分別表示除數(shù)、商的小數(shù)點(diǎn)后的位數(shù)和近似值的處理模式,下表是給大家列出的roundingMode參數(shù)支持的處理模式。
模式名稱 | 說明 |
---|---|
BigDecimal.ROUND_UP | 商的最后一位,如果大于 0,則向前進(jìn)位,正負(fù)數(shù)都如此。 |
BigDecimal.ROUND_DOWN | 商的最后一位無論是什么數(shù)字都省略 |
BigDecimal.ROUND_CEILING | 商如果是正數(shù),按照 ROUND_UP 模式處理;如果是負(fù)數(shù),按照 ROUND_DOWN模式處理 |
BigDecimal.ROUND_FLOOR | 與 ROUND_CELING 模式相反,商如果是正數(shù),按照 ROUND_DOWN 模式處理;如果是負(fù)數(shù),按照 ROUND_UP 模式處理 |
BigDecimal.ROUND_HALF_ DOWN | 對商進(jìn)行五舍六入操作。如果商最后一位小于等于 5,則做舍棄操作,否則對最后一位進(jìn)行進(jìn)位操作 |
BigDecimal.ROUND_HALF_UP | 對商進(jìn)行四舍五入操作。如果商最后一位小于 5,則做舍棄操作,否則對最后一位進(jìn)行進(jìn)位操作 |
BigDecimal.ROUND_HALF_EVEN | 如果商的倒數(shù)第二位是奇數(shù),則按照 ROUND_HALF_UP 處理;如果是偶數(shù),則按照 ROUND_HALF_DOWN 處理 |
import java.math.BigDecimal; import java.math.RoundingMode; /** * @author 一一哥Sun */ public class Demo12 { public static void main(String[] args) { BigDecimal d1 = new BigDecimal("123.456"); BigDecimal d2 = new BigDecimal("123.456789"); // 會產(chǎn)生ArithmeticException異常,因?yàn)槌槐M,可以設(shè)置RoundingMode,按照指定的方法進(jìn)行四舍五入或者直接截?cái)啵? //BigDecimal d3 = d1.divide(d2); // 保留10位小數(shù)并四舍五入 BigDecimal d4 = d1.divide(d2, 10, RoundingMode.HALF_UP); System.out.println("d4="+d4); //按指定的位數(shù)直接截?cái)啵?.xxxx BigDecimal d5 = d1.divide(d2, 4, RoundingMode.DOWN); System.out.println("d5="+d5); } }
2.4 divideAndRemainder()除法
而divideAndRemainder()方法,會返回一個(gè)數(shù)組,內(nèi)部包含兩個(gè)BigDecimal,分別是商和余數(shù),其中商總是整數(shù),余數(shù)不會大于除數(shù),所以我們可以利用這個(gè)方法來判斷兩個(gè)BigDecimal是否是整數(shù)倍數(shù)。
import java.math.BigDecimal; import java.math.RoundingMode; /** * @author */ public class Demo12 { public static void main(String[] args) { //divideAndRemainder方法,返回一個(gè)數(shù)組,該數(shù)組內(nèi)部包含了兩個(gè)BigDecimal,分別是商和余數(shù),其中商總是整數(shù),余數(shù)不會大于除數(shù)。 //我們可以利用這個(gè)特性來判斷兩個(gè)BigDecimal是否是整數(shù)倍數(shù)。 BigDecimal n = new BigDecimal("123.456"); BigDecimal m = new BigDecimal("0.123"); BigDecimal[] dr = n.divideAndRemainder(m); System.out.println(dr[0]); // 1003 System.out.println(dr[1]); // 0.087 if (dr[1].signum() == 0) { // n是m的整數(shù)倍 System.out.println("n是m的整數(shù)倍"); }else { System.out.println("n不是m的整數(shù)倍"); } } }
3. 比較兩個(gè)BigDecimal
如果我們想比較兩個(gè)BigDecimal的值是否相等,需要特別注意,請不要使用equals()方法,因?yàn)槭褂迷摲绞竭M(jìn)行比較時(shí),不但要求兩個(gè)BigDecimal的值相等,還要求它們的scale()結(jié)果也相等。所以一般是建議使用compareTo()方法來比較,它會根據(jù)兩個(gè)值的大小分別返回負(fù)數(shù)、正數(shù)和0,分別表示小于、大于和等于。如下所示:
import java.math.BigDecimal; /** * @author */ public class Demo13 { public static void main(String[] args) { BigDecimal d1 = new BigDecimal("123.456"); BigDecimal d2 = new BigDecimal("123.456000"); // false,因?yàn)閟cale不同 System.out.println("d1==d2? "+d1.equals(d2)); // true,因?yàn)閐2去除尾部0后scale變?yōu)? System.out.println("d1==d2? "+d1.equals(d2.stripTrailingZeros())); //結(jié)果=0,負(fù)數(shù)表示小于,正數(shù)表示大于,0表示等于 System.out.println("d1==d2? "+d1.compareTo(d2)); } }
之所以需要使用compareTo()方法來比較兩個(gè)BigDecimal的值才準(zhǔn)確,這是因?yàn)橐粋€(gè)BigDecimal實(shí)際上由一個(gè)BigInteger和一個(gè)scale組合而成的,其中BigInteger表示一個(gè)完整的整數(shù),scale表示小數(shù)位數(shù)。如下圖所示:
compareTo()方法內(nèi)部會對小數(shù)位數(shù)進(jìn)行判斷,所以更準(zhǔn)確,如下圖:
三. 結(jié)語
至此,就把BigInteger、BigDecimal等大數(shù)字類介紹完畢了,最后給大家總結(jié)一下今天的重點(diǎn)內(nèi)容:
- BigInteger 用于表示任意大小的整數(shù);
- BigInteger 是不變類,并且繼承自 Number ;
- 將 BigInteger 轉(zhuǎn)換成基本類型時(shí)可使用 longValueExact() 等方法保證結(jié)果準(zhǔn)確;
- BigDecimal 用于表示精確的小數(shù),常用于財(cái)務(wù)計(jì)算;
- 比較 BigDecimal 的值是否相等,必須使用 compareTo() 而不能使用 equals()。
以上就是Java中BigInteger與BigDecimal類用法總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Java BigInteger與BigDecimal類的資料請關(guān)注腳本之家其它相關(guān)文章!
- Java BigInteger類,BigDecimal類,Date類,DateFormat類及Calendar類用法示例
- JAVA基本類型包裝類 BigDecimal BigInteger 的使用
- Java你不了解的大數(shù)型BigInteger與BigDecimal類
- Java Big Number操作BigInteger及BigDecimal類詳解
- JAVA?biginteger類bigdecimal類的使用示例學(xué)習(xí)
- java數(shù)學(xué)類Math?BigInteger?BigDecimal使用介紹
- Java中的System類、BigInteger類和BigDecimal類詳解
- JavaAPI中BigInteger、BigDecimal的使用方法及應(yīng)用
相關(guān)文章
java中SpringBoot?自動(dòng)裝配的原理分析
這篇文章主要介紹了SpringBoot?自動(dòng)裝配的原理分析的相關(guān)資料,需要的朋友可以參考下2022-12-12Java實(shí)現(xiàn)郵箱找回密碼實(shí)例代碼
本篇文章主要介紹了Java實(shí)現(xiàn)郵箱找回密碼實(shí)例代碼,可以通過郵箱找回丟失密碼,具有一定的參考價(jià)值,有需要的可以了解一下。2016-11-11Java日期轉(zhuǎn)換注解配置date?format時(shí)間失效
這篇文章主要為大家介紹了Java日期轉(zhuǎn)換注解配置date?format時(shí)間失效,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Java中使用Preconditions來檢查傳入?yún)?shù)介紹
這篇文章主要介紹了Java中使用Preconditions來檢查傳入?yún)?shù)介紹,本文只是作為一個(gè)簡單的用法介紹,需要的朋友可以參考下2015-06-06Spring?Boot實(shí)現(xiàn)多數(shù)據(jù)源連接和切換的解決方案
文章介紹了在SpringBoot中實(shí)現(xiàn)多數(shù)據(jù)源連接和切換的幾種方案,并詳細(xì)描述了一個(gè)使用AbstractRoutingDataSource的實(shí)現(xiàn)步驟,感興趣的朋友一起看看吧2025-01-01Java模擬死鎖發(fā)生之演繹哲學(xué)家進(jìn)餐問題案例詳解
這篇文章主要介紹了Java模擬死鎖發(fā)生之演繹哲學(xué)家進(jìn)餐問題,結(jié)合具體演繹哲學(xué)家進(jìn)餐問題的案例形式詳細(xì)分析了死鎖機(jī)制與原理,需要的朋友可以參考下2019-10-10