在Java/Android中,BigDecimal 用于高精度的十进制运算。以下是详细的转换和操作方法:
1. 创建和初始化
基本创建方式
java
import java.math.BigDecimal;
import java.math.RoundingMode;
// 1. 使用字符串创建(推荐,避免精度问题)
BigDecimal bd1 = new BigDecimal("123.456");
BigDecimal bd2 = new BigDecimal("100.00");
// 2. 使用double创建(可能有不精确问题)
BigDecimal bd3 = new BigDecimal(123.456);
// 3. 使用valueOf方法(内部会处理double的精度问题)
BigDecimal bd4 = BigDecimal.valueOf(123.456);
BigDecimal bd5 = BigDecimal.valueOf(100);
// 4. 使用整数创建
BigDecimal bd6 = new BigDecimal(100);
BigDecimal bd7 = BigDecimal.valueOf(100L);
// 5. 常用常量
BigDecimal zero = BigDecimal.ZERO;
BigDecimal one = BigDecimal.ONE;
BigDecimal ten = BigDecimal.TEN;
2. 基本算术运算
四则运算
java
BigDecimal a = new BigDecimal("10.50");
BigDecimal b = new BigDecimal("3.20");
// 加法
BigDecimal sum = a.add(b); // 13.70
// 减法
BigDecimal difference = a.subtract(b); // 7.30
// 乘法
BigDecimal product = a.multiply(b); // 33.600
// 除法(需要指定精度和舍入模式)
BigDecimal quotient = a.divide(b, 2, RoundingMode.HALF_UP); // 3.28
// 取余
BigDecimal remainder = a.remainder(b); // 0.90
复杂运算示例
java
public class BigDecimalOperations {
public static void main(String[] args) {
BigDecimal price = new BigDecimal("99.99");
BigDecimal quantity = new BigDecimal("3");
BigDecimal taxRate = new BigDecimal("0.08"); // 8%
// 计算总金额
BigDecimal subtotal = price.multiply(quantity);
// 计算税费
BigDecimal tax = subtotal.multiply(taxRate)
.setScale(2, RoundingMode.HALF_UP);
// 计算最终金额
BigDecimal total = subtotal.add(tax);
System.out.println("小计: $" + subtotal); // $299.97
System.out.println("税费: $" + tax); // $24.00
System.out.println("总计: $" + total); // $323.97
}
}
3. 精度控制和舍入
设置精度和舍入模式
java
BigDecimal number = new BigDecimal("123.456789");
// 设置小数位数
BigDecimal scaled1 = number.setScale(2, RoundingMode.HALF_UP); // 123.46
BigDecimal scaled2 = number.setScale(4, RoundingMode.FLOOR); // 123.4567
// 除法时的精度控制
BigDecimal a = new BigDecimal("10");
BigDecimal b = new BigDecimal("3");
// 指定小数位数和舍入模式
BigDecimal result1 = a.divide(b, 4, RoundingMode.HALF_UP); // 3.3333
BigDecimal result2 = a.divide(b, 2, RoundingMode.CEILING); // 3.34
舍入模式详解
java
BigDecimal number = new BigDecimal("123.456");
// 常用舍入模式
BigDecimal halfUp = number.setScale(2, RoundingMode.HALF_UP); // 123.46
BigDecimal halfDown = number.setScale(2, RoundingMode.HALF_DOWN); // 123.46
BigDecimal halfEven = number.setScale(2, RoundingMode.HALF_EVEN); // 123.46
BigDecimal ceiling = number.setScale(2, RoundingMode.CEILING); // 123.46
BigDecimal floor = number.setScale(2, RoundingMode.FLOOR); // 123.45
BigDecimal up = number.setScale(2, RoundingMode.UP); // 123.46
BigDecimal down = number.setScale(2, RoundingMode.DOWN); // 123.45
4. 比较操作
大小比较
java
BigDecimal a = new BigDecimal("100.50");
BigDecimal b = new BigDecimal("100.00");
BigDecimal c = new BigDecimal("100.50");
// 比较
int compareResult = a.compareTo(b); // 1 (a > b)
boolean isGreater = a.compareTo(b) > 0; // true
boolean isLess = a.compareTo(b) < 0; // false
boolean isEqual = a.compareTo(c) == 0; // true
// 不要使用equals进行数值比较(会比较精度)
boolean equals1 = a.equals(b); // false
boolean equals2 = a.equals(new BigDecimal("100.5")); // false(精度不同)
boolean compare1 = a.compareTo(new BigDecimal("100.5")) == 0; // true
范围检查
java
public class BigDecimalComparison {
public static boolean isBetween(BigDecimal value, BigDecimal min, BigDecimal max) {
return value.compareTo(min) >= 0 && value.compareTo(max) <= 0;
}
public static boolean isPositive(BigDecimal value) {
return value.compareTo(BigDecimal.ZERO) > 0;
}
public static boolean isNegative(BigDecimal value) {
return value.compareTo(BigDecimal.ZERO) < 0;
}
public static boolean isZero(BigDecimal value) {
return value.compareTo(BigDecimal.ZERO) == 0;
}
}
5. 类型转换
转换为其他类型
java
BigDecimal bd = new BigDecimal("123.456");
// 转换为字符串
String stringValue = bd.toString(); // "123.456"
String plainString = bd.toPlainString(); // "123.456"(不使用科学计数法)
String engineeringString = bd.toEngineeringString(); // "123.456"
// 转换为数值类型
int intValue = bd.intValue(); // 123(直接截断)
long longValue = bd.longValue(); // 123
float floatValue = bd.floatValue(); // 123.456
double doubleValue = bd.doubleValue(); // 123.456
// 安全转换(处理null和异常)
int safeInt = bd.intValueExact(); // 如果非整数会抛出异常
long safeLong = bd.longValueExact(); // 同上
从其他类型转换
java
// 从字符串转换
BigDecimal fromString = new BigDecimal("123.45");
// 从数值类型转换
BigDecimal fromInt = BigDecimal.valueOf(100);
BigDecimal fromLong = BigDecimal.valueOf(100L);
BigDecimal fromDouble = BigDecimal.valueOf(123.456);
// 从整数转换
BigDecimal fromInteger = new BigDecimal(100);
// 处理null安全的转换
public static BigDecimal safeValueOf(String value) {
if (value == null || value.trim().isEmpty()) {
return BigDecimal.ZERO;
}
try {
return new BigDecimal(value.trim());
} catch (NumberFormatException e) {
return BigDecimal.ZERO;
}
}
6. 实用工具方法
数学运算
java
BigDecimal number = new BigDecimal("16");
// 绝对值
BigDecimal abs = number.abs();
// 取反
BigDecimal negate = number.negate();
// 次方运算
BigDecimal power = number.pow(2); // 256
// 移动小数点
BigDecimal movePoint = number.movePointRight(2); // 1600
BigDecimal movePointLeft = number.movePointLeft(1); // 1.6
精度操作
java
BigDecimal number = new BigDecimal("123.456789");
// 获取精度相关信息
int scale = number.scale(); // 6(小数位数)
int precision = number.precision(); // 9(总位数)
BigDecimal stripped = number.stripTrailingZeros(); // 去除末尾的0
// 检查整数
boolean isInteger = number.scale() <= 0; // false
boolean hasDecimal = number.scale() > 0; // true
7. 在Android中的实际应用
金额计算工具类
java
public class MoneyUtils {
/**
* 格式化金额显示
*/
public static String formatMoney(BigDecimal amount) {
if (amount == null) return "¥0.00";
DecimalFormat df = new DecimalFormat("¥#,##0.00");
return df.format(amount);
}
/**
* 安全地解析金额字符串
*/
public static BigDecimal parseMoney(String moneyStr) {
if (moneyStr == null || moneyStr.trim().isEmpty()) {
return BigDecimal.ZERO;
}
try {
// 移除货币符号和逗号
String cleaned = moneyStr.replaceAll("[¥$,]", "").trim();
return new BigDecimal(cleaned);
} catch (NumberFormatException e) {
return BigDecimal.ZERO;
}
}
/**
* 计算含税价格
*/
public static BigDecimal calculateTaxIncluded(BigDecimal amount, BigDecimal taxRate) {
if (amount == null || taxRate == null) {
return BigDecimal.ZERO;
}
BigDecimal tax = amount.multiply(taxRate)
.setScale(2, RoundingMode.HALF_UP);
return amount.add(tax);
}
/**
* 分配金额(如AA制分摊)
*/
public static BigDecimal[] splitAmount(BigDecimal total, int parts) {
if (total == null || parts <= 0) {
return new BigDecimal[0];
}
BigDecimal[] result = new BigDecimal[parts];
BigDecimal partAmount = total.divide(BigDecimal.valueOf(parts), 2, RoundingMode.HALF_UP);
// 前n-1个部分使用平均分配
for (int i = 0; i < parts - 1; i++) {
result[i] = partAmount;
}
// 最后一部分用总金额减去已分配金额,避免精度损失
BigDecimal allocated = partAmount.multiply(BigDecimal.valueOf(parts - 1));
result[parts - 1] = total.subtract(allocated);
return result;
}
}
在Activity中使用
java
public class PaymentActivity extends AppCompatActivity {
private TextView totalAmountView;
private EditText quantityEditText;
private BigDecimal unitPrice = new BigDecimal("29.99");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_payment);
totalAmountView = findViewById(R.id.totalAmount);
quantityEditText = findViewById(R.id.quantity);
quantityEditText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
calculateTotal();
}
// 其他方法...
});
}
private void calculateTotal() {
try {
String quantityStr = quantityEditText.getText().toString();
if (quantityStr.isEmpty()) {
totalAmountView.setText("¥0.00");
return;
}
BigDecimal quantity = new BigDecimal(quantityStr);
BigDecimal total = unitPrice.multiply(quantity)
.setScale(2, RoundingMode.HALF_UP);
totalAmountView.setText(MoneyUtils.formatMoney(total));
} catch (NumberFormatException e) {
totalAmountView.setText("无效数量");
}
}
/**
* 处理折扣计算
*/
private BigDecimal applyDiscount(BigDecimal original, BigDecimal discountRate) {
BigDecimal discount = original.multiply(discountRate)
.setScale(2, RoundingMode.HALF_UP);
return original.subtract(discount);
}
}
8. 注意事项
重要提醒
java
// 1. 始终使用字符串构造BigDecimal来避免精度问题
BigDecimal bad = new BigDecimal(0.1); // 不推荐
BigDecimal good = new BigDecimal("0.1"); // 推荐
// 2. 比较使用compareTo而不是equals
BigDecimal a = new BigDecimal("100.0");
BigDecimal b = new BigDecimal("100.00");
boolean wrong = a.equals(b); // false
boolean correct = a.compareTo(b) == 0; // true
// 3. 除法一定要指定舍入模式
BigDecimal ten = new BigDecimal("10");
BigDecimal three = new BigDecimal("3");
// BigDecimal error = ten.divide(three); // 会抛出ArithmeticException
BigDecimal correct = ten.divide(three, 2, RoundingMode.HALF_UP); // 3.33
// 4. 使用valueOf来处理double(内部会处理精度)
BigDecimal fromDouble = BigDecimal.valueOf(0.1); // 0.1
这些是BigDecimal在Java/Android中的主要转换和操作方法。BigDecimal特别适合财务计算、货币运算等需要高精度的场景。