Java工具類——數學相關的類 在上一篇文章中,我們系統學習了 Java 裡面的包裝類,那麼這篇文章,我們就來學習一下Java提供好的類——數學相關的類。 一、數學類介紹 在最早期學習 Java 基礎語法結構的時候,其實我們學習並瞭解了加減乘除這些算數運算符,有了這些運算符,我們就可以做一些簡單的運 ...
Java工具類——數學相關的類
在上一篇文章中,我們系統學習了 Java 裡面的包裝類,那麼這篇文章,我們就來學習一下Java提供好的類——數學相關的類。
一、數學類介紹
在最早期學習 Java 基礎語法結構的時候,其實我們學習並瞭解了加減乘除這些算數運算符,有了這些運算符,我們就可以做一些簡單的運算了,但是當我們需要做一些比較複雜的運算的時候,其實用這些運算符是很難去處理的(比如獲取隨機數等等)。其實數學類對於我們並不陌生,在學習 Java 基礎的時候,你一定用過 Math 類的,這個其實就是我們最早期接觸的一個數學類了,其實與數學相關的類還有 BigInteger 類、BigDecimal 類等等,下麵這個表格將這三個類做了一個小的梳理總結:
數學類 | 所屬包 | 繼承關係 |
---|---|---|
Math類 | java.lang包,不需要導包 | 預設繼承Object基類 |
BigInteger類 | java.math包,需要導包 | 繼承自Number類,實現了Serializable, Comparable介面 |
BigDecimal類 | java.math包,需要導包 | 繼承自Number類,實現了Serializable, Comparable介面 |
下麵我們就對這三種類做一個詳細的學習。
二、Math類
其實看源碼我們看到,Math 這個類是 final 修飾的,意思就是不能讓子類去繼承的,只能使用這個類。
public final class Math {}
下麵,我們來詳細瞭解一下Math類
1、Math類構造方法
通過看源碼,我們可以得知 Math 這個類的構造方法是私有的,也就是我們是不能創建對象的,為什麼會這樣設計呢,其實是因為 Math 類裡面的屬性和方法都是靜態的( static 修飾)。
/**
* Don't let anyone instantiate this class.
*/
private Math() {}
2、Math類常用的方法
- abs()方法返回給定數的絕對值,方法提供了4個不同參數類型重載方法(int, long, float, double)
int abs1 = Math.abs(-1);
long abs2 = Math.abs(-3l);
float abs3 = Math.abs(-1.2f);
double abs4 = Math.abs(-3.923);
System.out.println(abs1);
System.out.println(abs2);
System.out.println(abs3);
System.out.println(abs4);
- ceil()方法返回大於或等於參數且等於一個數學整數的最小的雙精度值,可以理解為向上取整。
System.out.println(Math.ceil(-1.3));//-1.0
System.out.println(Math.ceil(1.9));//2.0
System.out.println(Math.ceil(-7.9));//-7.0
System.out.println(Math.ceil(123));//123.0
- floor()方法返回最大的雙精度值,該雙精度值小於或等於參數,並且等於一個數學整數,可以理解為向下取整。
System.out.println(Math.floor(-1.3));//-2.0
System.out.println(Math.floor(1.9));//1.0
System.out.println(Math.floor(1.3));//1.0
System.out.println(Math.floor(-7.9));//-8.0
System.out.println(Math.floor(123));//123.0
- round()方法返回與參數最接近的整型數,四捨五入為正無窮,其實就是四捨五入的整數。
System.out.println(Math.round(-1.3));//-1
System.out.println(Math.round(1.9));//2
System.out.println(Math.round(1.3));//1
System.out.println(Math.round(-7.9));//-8
System.out.println(Math.round(123));//123
- max()方法返回最大值,該方法提供了4個不同參數類型重載方法(int,long,float,double)
System.out.println(Math.max(1, 3));//3
System.out.println(Math.max(-4, -5));//-4
System.out.println(Math.max(1.8, 1.92));//1.92
System.out.println(Math.max(-4f, -4f));//-4.0
- min(a, b)方法返回最小值,該方法提供了4個不同參數類型重載方法(int, long, float, double)
System.out.println(Math.min(1, 3));//1
System.out.println(Math.min(-4, -5));//-5
System.out.println(Math.min(1.8, 1.92));//1.8
System.out.println(Math.min(-4f, -4f));//-4.0
- pow(a, b)方法返回 a 的 b 次方,其中參數和返回值都是 double 類型的
System.out.println(Math.pow(3, 3));//27.0
System.out.println(Math.pow(3.2, 5));//335.5443200000001
- random()方法生成一個 double 類型的隨機數,範圍是[ 0.0, 1.0),註意是左閉右開。
System.out.println(Math.random());//0.4128879706448445
System.out.println(Math.random());//0.9024029619163387
System.out.println(Math.random());//0.4265563513755902
三、BigInteger類
我們都知道,在基本數據類型裡面,long型的取值範圍是最大的,也就是8個位元組,取值範圍是-2的63次方到正的2的63次方減去1,當然,這個取值範圍很大很大,在平時的開發中,我們其中只用到int類型的都基本夠了,但是當我們存儲的數據的長度超過了 long 型的長度時,我們該怎麼存儲呢?這時候,BigInteger 類就可以解決我們的問題。
BigInteger 顧名思義,其實就是叫大整數,也就是說只能存儲整型的數,我們通過構造方法和常用方法來瞭解BigInteger 類。
1、構造方法
BigInteger 類有8個構造方法,其中有2個私有構造方法。8個構造方法分別是:
private BigInteger(int[] val){}
private BigInteger(int signum, int[] magnitude){}
public BigInteger(byte[] val){}
public BigInteger(String val){}
public BigInteger(String val, int radix) {}
public BigInteger(int signum, byte[] magnitude){}
public BigInteger(int numBits, Random rnd){}
public BigInteger(int bitLength, int certainty, Random rnd){}
2、類中常用的方法
當我們想用這個類做四則運算的時候,是不是也可以直接加減乘除呢,比如下麵這張圖:
通過上面這張圖,BigInteger類直接做四則運算顯然是不可以的,因為上面兩個數是引用類型,而運算符只能對基本數據類型做運算。那麼我們怎麼做相應的四則運算呢?其實BigInteger類裡面其實已經幫我們實現對應的方法,我們直接用實例化的的對象調用它就行了。比如下方的代碼進行加減乘除:
private static void test6() {
BigInteger num1 = new BigInteger("1111");
BigInteger num2 = new BigInteger("2222");
//加法
BigInteger add = num1.add(num2);
//減法
BigInteger subtract = num2.subtract(num1);
//乘法
final BigInteger multiply = num1.multiply(num2);
//除法(取整)
BigInteger divide = num2.divide(num1);
//除法(取餘)
BigInteger mod = num2.mod(num1);
System.out.println(add);//3333
System.out.println(subtract);//1111
System.out.println(multiply);//2468642
System.out.println(divide);//2
System.out.println(mod);//0
}
四、BigDecimal類
與 BigInteger 類對應的是 BigDecimal 類,BigInteger 是處理整數的,而 BigDecimal 是處理小數的,Decimal 英文單詞就是小數的意思,所以 BigDecimal 顧名思義就是大小數,處理大的小數的。如果一個小數超過了 double類型的取值範圍,就需要用到 BigDecimal。
1、構造方法
BigDecimal 類的構造方法有很多,最常用的是以下四個:
public BigDecimal(double val) {
public BigDecimal(int val) {}
public BigDecimal(String val) {}
public BigDecimal(long val) {}
2、類中常用的方法
和 BigInteger 類一樣,BigDecimal 也是不可以直接進行加減乘除的,加減乘除的方式和 BigInteger 處理方式一樣,比如下麵的代碼對BigDecimal 進行四則運算:
private static void test7() {
BigDecimal num1 = new BigDecimal("1.23");
BigDecimal num2 = new BigDecimal("2.46");
//加法
BigDecimal add = num1.add(num2);
//減法
BigDecimal subtract = num2.subtract(num1);
//乘法
final BigDecimal multiply = num1.multiply(num2);
//除法(取整)
BigDecimal divide = num2.divide(num1);
System.out.println(add);//3.69
System.out.println(subtract);//1.23
System.out.println(multiply);//3.0258
System.out.println(divide);//2
}
由於小數和整數不一樣,小數經常涉及到精度的問題,所以 BigDecimal 裡面也提供了方法來設置小數的精度,設置精度的方法有三個重載的方法:
public BigDecimal setScale(int newScale)
public BigDecimal setScale(int newScale, int roundingMode)
public BigDecimal setScale(int newScale, RoundingMode roundingMode)
這三個方法的第一個參數是設置保留小數點之後的位數,第二個參數是設置的模式(比如向上取整還是向下取整等等),設置四捨五入的模式有8種:
public final static int ROUND_UP = 0;
public final static int ROUND_DOWN = 1;
public final static int ROUND_CEILING = 2;
public final static int ROUND_FLOOR = 3;
public final static int ROUND_HALF_UP = 4;
public final static int ROUND_HALF_DOWN = 5;
public final static int ROUND_HALF_EVEN = 6;
public final static int ROUND_UNNECESSARY = 7;
下麵我們就來對這其中4種模式的用法做一個詳細的分析
- ROUND_UP 模式
UP的意思就是向上的意思,可以理解為加的意思。比如我保留了三位小數,那麼我不管你後面的小數值如何(除了0),我都給你加一,就相當於四捨五入的五入。比如下麵這個代碼,我保留3為小數,模式設置為ROUND_UP模式,那麼如果最後一位是0,那麼結果就是9.461,否則就是9.462
BigDecimal bigDecimal = new BigDecimal("9.4610");
BigDecimal result = bigDecimal.setScale(3, BigDecimal.ROUND_UP);
- ROUND_DOWN 模式
是一個舍位取值的概念,比如我保留了三位小數,那麼我不管你後面的小數值如何,也不會四捨五入,就硬生生的的截斷,相當於什麼呢,就是我從小數點後面開始取三位,三位後面的都不要了。比如下麵這個代碼,我保留3為小數,模式設置為ROUND_DOWN模式,那麼最後一位不管是什麼(從0到9),最後的結果都是9.461
BigDecimal bigDecimal = new BigDecimal("9.4611");
BigDecimal result = bigDecimal.setScale(3, BigDecimal.ROUND_DOWN);
- ROUND_CEILING 模式
這個模式就是給定的數如果為正數,行為和ROUND_UP一樣,如果為負數,行為和ROUND_DOWN一樣 。
- ROUND_FLOOR 模式
這個模式就是給定的數如果為正數,行為和ROUND_DOWN一樣,如果為負數,行為和ROUND_UP一樣
五、小結
以上就是我對數學相關類的總結以及個人的理解,如果有任何不清楚的,可以去看官方文檔(API官方文檔地址:https://docs.oracle.com/javase/8/docs/api/),其實,很多人都很排斥看源碼和閱讀官網文檔,原因就是源碼和閱讀官網文檔都是全英文的,解讀起來很費時間;其實這是一種不好的學習方式,源碼和閱讀官網文檔是最官方權威的第一手資料,也是最正確的,如果我們去網上看其他的相關解讀,這也只能是他人的解讀,而其他人的解讀就代表了他對源碼和閱讀官網文檔的個人理解,而這個理解是可能會有出入的,也就是可能會誤導我們,所以我們一定要養成習慣去閱讀源碼和閱讀官網文檔,可能剛開始的確很慢,但是慢慢的就你的閱讀速度和效率就會提高的。
公眾號:良許Linux