在 Java 中將整數轉換為 BigDecimal
瀏覽人數:315最近更新:
1. 概述
BigDecimal
設計用於處理大浮點數。它解決了浮點運算的問題,並提供了一種控制精度的方法。此外,它還有很多傳統的數位運算方法。
我們可以透過轉換Integer
來利用BigDecimal
的功能。在本教程中,我們將學習幾種方法來執行此操作並討論它們的優點和缺點。
2. 建構函數轉換
使用建構函數轉換的最直接方法之一。 BigDecimal
公開了可以從各種輸入進行轉換的建構子。因此,我們可以將給定的Integer
傳遞給BigDecimal
建構子:
@ParameterizedTest
@ArgumentsSource(BigDecimalConversionArgumentsProvider.class)
void giveIntegerWhenConvertWithConstructorToBigDecimalThenConversionCorrect(Integer given, BigDecimal expected) {
BigDecimal actual = new BigDecimal(given);
assertThat(actual).isEqualTo(expected);
}
然而,透過這種方法,我們將強制 BigDecimal 每次創建一個新物件:
@ParameterizedTest
@ValueSource(ints = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
void giveIntegerWhenConvertWithConstructorToBigDecimalThenConversionWithoutCaching(Integer given) {
BigDecimal firstBigDecimal = new BigDecimal(given);
BigDecimal secondBigDecimal = new BigDecimal(given);
assertThat(firstBigDecimal)
.isEqualTo(secondBigDecimal)
.isNotSameAs(secondBigDecimal);
}
3. 靜態工廠轉換
另一種技術涉及靜態工廠,它與前面的範例類似:
@ParameterizedTest
@ArgumentsSource(BigDecimalConversionArgumentsProvider.class)
void giveIntegerWhenConvertWithValueOfToBigDecimalThenConversionCorrect(Integer given, BigDecimal expected) {
BigDecimal actual = BigDecimal.valueOf(given);
assertThat(actual).isEqualTo(expected);
}
它提供了一個好處:與建構函數轉換不同,它可以緩存值。因此,我們可以在不同的上下文中重複使用同一個物件。由於BigDecimal
是不可變的,因此不會產生任何問題。
4. 快取
BigIntegers.valueOf()
工廠快取從零到十的值。所有值都在BigDecimal
類別內的靜態ZERO_THROUGH_TEN
數組中定義:
private static final BigDecimal[] ZERO_THROUGH_TEN = {
new BigDecimal(BigInteger.ZERO, 0, 0, 1),
new BigDecimal(BigInteger.ONE, 1, 0, 1),
new BigDecimal(BigInteger.TWO, 2, 0, 1),
new BigDecimal(BigInteger.valueOf(3), 3, 0, 1),
new BigDecimal(BigInteger.valueOf(4), 4, 0, 1),
new BigDecimal(BigInteger.valueOf(5), 5, 0, 1),
new BigDecimal(BigInteger.valueOf(6), 6, 0, 1),
new BigDecimal(BigInteger.valueOf(7), 7, 0, 1),
new BigDecimal(BigInteger.valueOf(8), 8, 0, 1),
new BigDecimal(BigInteger.valueOf(9), 9, 0, 1),
new BigDecimal(BigInteger.TEN, 10, 0, 2),
};
valueOf(long)
工廠在內部使用這個陣列:
public static BigDecimal valueOf(long val) {
if (val >= 0 && val < ZERO_THROUGH_TEN.length)
return ZERO_THROUGH_TEN[(int)val];
else if (val != INFLATED)
return new BigDecimal(null, val, 0, 0);
return new BigDecimal(INFLATED_BIGINT, val, 0, 0);
}
我們可以看到,對於某些值, BigDecimal
物件是相同的:
@ParameterizedTest
@ValueSource(ints = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
void giveIntegerWhenConvertWithValueOfToBigDecimalThenConversionCachesTheResults(Integer given) {
BigDecimal firstBigDecimal = BigDecimal.valueOf(given);
BigDecimal secondBigDecimal = BigDecimal.valueOf(given);
assertThat(firstBigDecimal).isSameAs(secondBigDecimal);
}
如果我們使用從零到十的許多BigDecimal
值,這可能會提高效能。此外,由於BigDecimal
物件是不可變的,因此我們可以為應用程式中重複使用的數位實現快取。
同時,超出這個範圍的數字不會使用快取:
@ParameterizedTest
@ValueSource(ints = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21})
void giveIntegerWhenConvertWithValueOfToBigDecimalThenConversionWontCacheTheResults(Integer given) {
BigDecimal firstBigDecimal = BigDecimal.valueOf(given);
BigDecimal secondBigDecimal = BigDecimal.valueOf(given);
assertThat(firstBigDecimal)
.isEqualTo(secondBigDecimal)
.isNotSameAs(secondBigDecimal);
}
因此,在生產程式碼中依賴身份平等是不可取的。
5. 結論
當我們需要對浮點數進行運算時, BigDecimal
是一個不錯的選擇,避免捨入錯誤。此外,它還允許我們使用無法以其他方式表示的大量數字。 BigDecimal
提供了多種從其他類型(例如Integer
進行轉換的方法。
與往常一樣,本教程中的所有程式碼都可以在 GitHub 上取得。
本作品係原創或者翻譯,採用《署名-非商業性使用-禁止演繹4.0國際》許可協議