你好!在今天的講座中,我們將討論大數。不,關於真正大的。 之前,我們不只一次看到原始資料類型的值範圍表。它看起來像這樣:
如果我們談論整數,最大容量的資料類型是long,而當我們談論浮點數時,最大容量的資料類型是 double。但是,如果我們需要的數字太大,甚至無法放入long呢?可能的 Long 值的範圍相當大,但仍限制在一定的大小 - 64 位元。如果我們的超大數有 100 位,我們能得到什麼結果?幸運的是,您不需要發明任何東西。在 Java 中,為這種情況創建了兩個特殊的類別 - BigInteger(用於整數)和BigDecimal(用於浮點數)。他們的特點是什麼?首先,理論上它們沒有最大尺寸。理論上,因為不存在具有無限內存的計算機。而如果你在程式中建立的數字大於電腦記憶體的大小,當然程式將無法運作。但這種情況不太可能發生。因此,我們可以說數字的大小實際上
原始型 | 記憶體大小 | 數值範圍 |
---|---|---|
位元組 | 8位 | -128 至 127 |
短的 | 16位 | 至 -32768 至 32767 |
字元 | 16位 | 從 0 到 65536 |
整數 | 32位 | 從-2147483648 到 2147483647 |
長的 | 64位 | 從-9223372036854775808到9223372036854775807 |
漂浮 | 32位 | 從 (2 的 -149 次方) 到 ((2-2 的 -23 次方)*2 的 127 次方) |
雙倍的 | 64位 | 由 (-2 的 63 次方) 到 ((2 的 63 次方) - 1) |
布林值 | 8(用於數組時)、32(用於非數組時) | 對或錯 |
BigInteger
是BigDecimal
無限的。這些類別是用來做什麼的?首先,對於精度要求極高的計算。例如,在某些程式中,人的生命可能取決於計算的準確性(飛機和火箭或醫療設備的軟體)。因此,如果連小數點後150位也發揮重要作用,BigDecimal
那麼它就是最好的選擇。此外,這些物件經常用於金融領域,其中最小數值的計算精度也極為重要。 如何使用物件BigInteger
以及BigDecimal
需要記住的重要事項是什麼? 這些類別的物件是這樣創建的:
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
BigDecimal decimal = new BigDecimal("123.444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
System.out.println(decimal);
}
}
將字串作為參數傳遞只是可能的建構函數之一。Here we use strings because our numbers exceed the maximum values long
and double
, and somehow we need to explain to the compiler exactly what number we want to get :) Just pass the number 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 to the constructor 1111111111111111111111111111111111111111111111111111111111111111111 will not work: Java will try to將傳遞的數字「適合」一種原始資料類型,但它不適合其中任何一種。因此,使用字串來傳遞所需的數字是一個不錯的選擇。這兩個類別都可以自動從傳遞的字串中提取數值。使用大量類別時要記住的另一個要點是它們的物件是不可變的 ( Immutable
)。String
透過類別和基元(Integer、Long 等)的包裝類別 的範例,您已經非常熟悉不變性原則。
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
integer.add(BigInteger.valueOf(33333333));
System.out.println(integer);
}
}
控制台輸出:
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
正如您所期望的,我們的數字沒有改變。為了使加法操作成功,您必須建立一個新物件並將加法結果指派給它。
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
BigInteger result = integer.add(BigInteger.valueOf(33333333));
System.out.println(result);
}
}
控制台輸出:
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
現在一切都正常了:) 順便說一句,您是否注意到加法操作看起來有多不尋常?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
這是另一個重要的一點。大量類別在其操作中不使用 +-*/ 運算符,而是提供一組方法。 讓我們來看看主要的方法(您可以一如既往地在 Oracle 文件中找到完整的方法清單:此處和此處)。
-
執行算術運算的方法:
add()
、subtract()
、multiply()
、divide()
。分別用於加、減、乘、除運算。 -
doubleValue()
,intValue()
,floatValue()
,longValue()
ETC。- 用於將大量數字轉換為 Java 基本類型。使用時要小心,記住容量的差異!import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); long result = integer.longValue(); System.out.println(result); } }
控制台輸出:
8198552921648689607
-
min()
和max()
- 允許您找到傳遞的兩個大數的最小值和最大值。
請注意:方法不是靜態的!import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); BigInteger integer2 = new BigInteger("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"); System.out.println(integer.max(integer2)); } }
控制台輸出:
222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
BigDecimal 捨入控制
這個主題包含在一個單獨的部分中,因為對大數進行舍入和調整並不是一件簡單的事情。BigDecimal
您可以使用 來設定數字的小數位數setScale()
。例如,我們要將數字111.5555555555的精度設定為小數點後三位。但是,我們將無法將數字 3 作為參數傳遞給該方法setScale()
,從而解決我們的問題。如上所述,BigDecimal
這些是用於提高精度的計算的數字。在目前的形式中,我們的數字有 10 位小數。我們想丟棄其中的 7 個,只留下 3 個。因此,除了數字 3 之外,我們還必須將舍入模式作為參數傳遞。 共有8種舍入模式BigDecimal
。非常多!但如果您需要真正微調程式中的運算精度,您將擁有所需的一切。因此,以下是 中可用的 8 種舍入模式BigDecimal
:
-
ROUND_CEILING
- 圍捕111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
-
ROUND_DOWN
- 排放丟棄111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
-
ROUND_FLOOR
- 向下舍入111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555
-
ROUND_HALF_UP
— 若小數點後的數字 >= .5,則四捨五入0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6 0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
-
ROUND_HALF_DOWN
— 若小數點後的數字 > .5,則四捨五入0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5 0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
-
ROUND_HALF_EVEN
— 四捨五入取決於小數點左邊的數字。如果左邊的數字是偶數,則向下捨去。如果小數點左邊的數字是奇數,則四捨五入。2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2
小數點左邊的數字 - 2 - 是偶數。向下舍入。由於我們要求小數點後 0 位,因此結果將為 2。
3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4
小數點左邊的數字 - 3 - 是奇數。向上舍入。由於我們要求小數點後 0 位,因此結果將為 4。
-
ROUND_UNNECCESSARY
— 用於需要將舍入模式傳遞給某種方法,但數字不需要捨入的情況。如果在設定 ROUND_UNNECCESSARY 模式時嘗試對數字進行舍入,則會引發 ArithmeticException。3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
-
ROUND_UP
- 圍捕。111.5551 -> setScale(3, ROUND_UP) -> 111.556
大數比較
這個問題也很重要。您已經記得該方法用於比較 Java 中的物件equals()
。它要么由語言本身提供(對於 Java 的內建類別),要么由程式設計師覆蓋。但對於類別物件的情況,不建議BigDecimal
使用此方法equals()
進行比較。原因是只有當BigDecimal.equals()
兩個數字有相同的值和小數位數時,雙數方法才會回傳true :讓我們比較一下y和 y方法的行為: equals()
Double
BigDecimal
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
Double a = 1.5;
Double b = 1.50;
System.out.println(a.equals(b));
BigDecimal x = new BigDecimal("1.5");
BigDecimal y = new BigDecimal("1.50");
System.out.println(x.equals(y));
}
}
控制台輸出:
true
false
正如您所看到的,在 c 的情況下,數字 1.5 和 1.50BigDecimal
原來是不相等的!equals()
發生這種情況正是因為類別中方法的特殊性BigDecimal
。為了更正確地比較兩者,BigDecimal
最好使用以下方法compareTo()
:
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal x = new BigDecimal("1.5");
BigDecimal y = new BigDecimal("1.50");
System.out.println(x.compareTo(y));
}
}
控制台輸出:
0
該方法compareTo()
傳回 0,這意味著等於 1.5 和 1.50。這就是我們所指望的結果!:) 今天的課程到此結束。是時候回去執行任務了!:)
GO TO FULL VERSION