BigInteger 和 BigDecimal 的实战指南
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
public class TestBigNumbers {
public static void main(String[] args) {
// 创建 BigInteger 对象
BigInteger numberA = new BigInteger("12345678901234567890");
BigInteger numberB = BigInteger.valueOf(100);
// 基本运算
BigInteger sum = numberA.add(numberB);
BigInteger difference = numberA.subtract(numberB);
BigInteger product = numberA.multiply(numberB);
BigInteger quotient = numberA.divide(numberB);
BigInteger remainder = numberA.remainder(numberB);
// 其他有用的方法
BigInteger absoluteValue = numberA.abs();
BigInteger negatedValue = numberA.negate();
int comparisonResult = numberA.compareTo(numberB);
// 创建 BigDecimal 对象
BigDecimal decimalX = new BigDecimal("12345.6789");
BigDecimal decimalY = BigDecimal.valueOf(10.5);
// 基本运算
BigDecimal decimalSum = decimalX.add(decimalY);
BigDecimal decimalDifference = decimalX.subtract(decimalY);
BigDecimal decimalProduct = decimalX.multiply(decimalY);
BigDecimal decimalQuotient = decimalX.divide(decimalY, 2, RoundingMode.HALF_UP);
// 其他有用的方法
BigDecimal decimalAbsValue = decimalX.abs();
BigDecimal decimalNegatedValue = decimalX.negate();
BigDecimal bi1 = new BigDecimal("0.1");
BigDecimal bi2 = new BigDecimal("0.2");
BigDecimal bi3 = new BigDecimal("0.1");
int compare1 = bi1.compareTo(bi2);
int compare2 = bi2.compareTo(bi1);
int compare3 = bi1.compareTo(bi3);
boolean equalsResult = bi1.equals(bi3);
System.out.println("BigInteger Operations:");
System.out.println("Sum: " + sum);
System.out.println("Difference: " + difference);
System.out.println("Product: " + product);
System.out.println("Quotient: " + quotient);
System.out.println("Remainder: " + remainder);
System.out.println("Absolute Value: " + absoluteValue);
System.out.println("Negated Value: " + negatedValue);
System.out.println("Comparison Result: " + comparisonResult);
System.out.println("\nBigDecimal Operations:");
System.out.println("Sum: " + decimalSum);
System.out.println("Difference: " + decimalDifference);
System.out.println("Product: " + decimalProduct);
System.out.println("Quotient: " + decimalQuotient);
System.out.println("Absolute Value: " + decimalAbsValue);
System.out.println("Negated Value: " + decimalNegatedValue);
System.out.println("Compare bi1 to bi2: " + compare1);
System.out.println("Compare bi2 to bi1: " + compare2);
System.out.println("Compare bi1 to bi3: " + compare3);
System.out.println("bi1 equals bi3: " + equalsResult);
}
}
BigInteger
受限于
- JVM 的最大堆大小
- 可用的物理内存
- 内部的
int
数组的最大长度,这也受限于 JVM 和物理内存 BigInteger
必须支持-2^Integer.MAX_VALUE
至2^Integer.MAX_VALUE
,即左右开区间- 超出范围会报
ArithmeticException
运算异常 - 最少支持 1 至 2^500000000
创建 BigInteger 对象
BigInteger numberA = new BigInteger("12345678901234567890");
BigInteger numberB = BigInteger.valueOf(100);
使用字符串创建 BigInteger
可以确保数值的准确性。通过 BigInteger.valueOf(long val)
方法可以快速创建较小的 BigInteger
对象。
Addition
BigInteger sum = numberA.add(numberB);
System.out.println("Sum: " + sum); // 12345678901234567990
add
方法用于两个 BigInteger
对象的加法运算。由于 BigInteger
是不可变的,add
方法返回一个新的 BigInteger
对象。
Subtraction
BigInteger difference = numberA.subtract(numberB);
System.out.println("Difference: " + difference); // 12345678901234567790
subtract
方法用于两个 BigInteger
对象的减法运算。返回一个新的 BigInteger
对象,表示差值。
Multiplication
BigInteger product = numberA.multiply(numberB);
System.out.println("Product: " + product); // 1234567890123456789000
multiply
方法用于两个 BigInteger
对象的乘法运算。返回一个新的 BigInteger
对象,表示积。
Division
BigInteger quotient = numberA.divide(numberB);
System.out.println("Quotient: " + quotient); // 123456789012345678
divide
方法用于两个 BigInteger
对象的除法运算。返回一个新的 BigInteger
对象,表示商。如果除不尽,会抛出 ArithmeticException
。
其他有用的方法
BigInteger absoluteValue = numberA.abs(); // 绝对值
BigInteger negatedValue = numberA.negate(); // 取反
int comparisonResult = numberA.compareTo(numberB); // 比较两个 BigInteger 的值
abs
返回BigInteger
的绝对值。negate
返回BigInteger
的相反数。compareTo
比较两个BigInteger
对象,返回负值、零或正值,分别表示小于、等于或大于。
BigDecimal
BigDecimal
用于表示任意大小的带有小数点的数,适用于高精度计算,如金融应用。
创建 BigDecimal 对象
BigDecimal decimalX = new BigDecimal("12345.6789");
BigDecimal decimalY = BigDecimal.valueOf(10.5);
使用字符串创建 BigDecimal
可以避免二进制浮点数带来的精度问题。BigDecimal.valueOf(double val)
也可以用于快速创建对象。
Addition
BigDecimal decimalSum = decimalX.add(decimalY);
System.out.println("Sum: " + decimalSum); // 12356.1789
add
方法用于两个 BigDecimal
对象的加法运算。返回一个新的 BigDecimal
对象,表示和。
Subtraction
BigDecimal decimalDifference = decimalX.subtract(decimalY);
System.out.println("Difference: " + decimalDifference); // 12335.6789
subtract
方法用于两个 BigDecimal
对象的减法运算。返回一个新的 BigDecimal
对象,表示差值。
Multiplication
BigDecimal decimalProduct = decimalX.multiply(decimalY);
System.out.println("Product: " + decimalProduct); // 129,999.00445
multiply
方法用于两个 BigDecimal
对象的乘法运算。返回一个新的 BigDecimal
对象,表示积。
Division
BigDecimal decimalQuotient = decimalX.divide(decimalY, 2, RoundingMode.HALF_UP);
System.out.println("Quotient: " + decimalQuotient); // 1177.73
divide
方法用于两个 BigDecimal
对象的除法运算。由于除法可能导致无限小数,需要指定精度和舍入模式,以确保结果的可控性。
其他有用的方法
BigDecimal decimalAbsValue = decimalX.abs(); // 绝对值
BigDecimal decimalNegatedValue = decimalX.negate(); // 取反
BigDecimal bi1 = new BigDecimal("0.1");
BigDecimal bi2 = new BigDecimal("0.2");
BigDecimal bi3 = new BigDecimal("0.1");
int compare1 = bi1.compareTo(bi2); // -1
int compare2 = bi2.compareTo(bi1); // 1
int compare3 = bi1.compareTo(bi3); // 0
boolean equalsResult = bi1.equals(bi3); // true
System.out.println("Compare bi1 to bi2: " + compare1);
System.out.println("Compare bi2 to bi1: " + compare2);
System.out.println("Compare bi1 to bi3: " + compare3);
System.out.println("bi1 equals bi3: " + equalsResult);
abs
返回BigDecimal
的绝对值。negate
返回BigDecimal
的相反数。compareTo
比较两个BigDecimal
对象,返回负值、零或正值。equals
检查两个BigDecimal
对象在数值和精度上是否相等。
注意事项
当使用 BigDecimal
进行除法操作时,通常需要指定精度和舍入模式,以确保得到期望的结果。此外,建议在初始化 BigDecimal
时使用字符串,以避免二进制浮点数带来的精度问题。
BigDecimal 的包装过程
BigDecimal
由两部分构成:
- 无符号整数值:由
BigInteger
表示,指代BigDecimal
的整数部分。 - 标度:一个
int
类型的值,定义小数点的位置。正数表示小数点后的位数,负数表示数值被扩大了多少倍。
以 3.154
为例:
- 无符号整数值为
3154
。 - 标度为
3
,因为小数点后有三位数字。
创建 BigDecimal
对象:
BigDecimal bd = new BigDecimal("3.154");
BigDecimal
会解析字符串 "3.154"
,并将其转化为上述的无符号整数值和标度。
为了确保数值的精确性,建议在初始化 BigDecimal
时使用字符串,而不是 double
或 float
类型。这是因为二进制浮点数可能不会精确地表示某些十进制数值,导致不期望的舍入。使用字符串初始化可以确保得到精确的数值表示。
注意事项
BigInteger
和 BigDecimal
都是不可变的类,这使得它们在多线程环境中天然安全。然而,频繁的对象创建会影响性能,尤其是在需要大量计算时。推荐在需要频繁修改数值的场景下使用 StringBuilder
或其他优化方法。
在处理国际化应用时,进行数值格式化等操作时,务必考虑区域性(Locale
)参数,以确保正确性。使用字符串方法时,注意可能抛出的异常,进行适当的异常处理或输入验证。理解这些类的内部结构和方法的工作原理,有助于编写高效、可靠的 Java 代码。
// 使用StringBuilder进行高效的字符串拼接
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("The sum is: ").append(sum);
System.out.println(stringBuilder.toString()); // The sum is: 12345678901234567990