跳到主要内容

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_VALUE2^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 时使用字符串,而不是 doublefloat 类型。这是因为二进制浮点数可能不会精确地表示某些十进制数值,导致不期望的舍入。使用字符串初始化可以确保得到精确的数值表示。

注意事项

BigIntegerBigDecimal 都是不可变的类,这使得它们在多线程环境中天然安全。然而,频繁的对象创建会影响性能,尤其是在需要大量计算时。推荐在需要频繁修改数值的场景下使用 StringBuilder 或其他优化方法。

在处理国际化应用时,进行数值格式化等操作时,务必考虑区域性(Locale)参数,以确保正确性。使用字符串方法时,注意可能抛出的异常,进行适当的异常处理或输入验证。理解这些类的内部结构和方法的工作原理,有助于编写高效、可靠的 Java 代码。

// 使用StringBuilder进行高效的字符串拼接
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("The sum is: ").append(sum);
System.out.println(stringBuilder.toString()); // The sum is: 12345678901234567990