ava中的float和double类型在表示小数时存在精度问题,因为它们是基于二进制浮点数的IEEE 754标准实现的。BigDecimal类可以解决这个问题,它提供了精确的小数运算能力。
从float/double创建BigDecimal
避免直接使用float或double的构造方法,因为这会传递不精确的值。推荐使用字符串构造方法:
float f = 0.1f;
double d = 0.1;
// 不推荐:可能引入不精确的值
BigDecimal bd1 = new BigDecimal(f);
BigDecimal bd2 = new BigDecimal(d);
// 推荐:使用字符串构造
BigDecimal bd3 = new BigDecimal("0.1");
BigDecimal bd4 = new BigDecimal(Float.toString(f));
BigDecimal bd5 = new BigDecimal(Double.toString(d));
设置精度和舍入模式
BigDecimal的运算需要指定舍入模式,常见的模式包括:
- RoundingMode.UP(进位):不管保留数字后面是大是小(0除外)都会进1。结果会向原点的反方向对齐,正数向正无穷方向对齐,负数向负无穷方向对齐。
- RoundingMode.DOWN(舍去):将要丢掉的数字直接丢掉。结果会向原点的反方向对齐,正数向正无穷方向对齐,负数向负无穷方向对齐。
- RoundingMode.CEILING(天花板):向上取整,即不管保留数字后面是大是小(0除外)都会进1,正数不变化,负数向正无穷方向对齐。
- RoundingMode.FLOOR(地板):向下取整,即将要丢掉的数字直接丢掉,正数向负无穷方向对齐,负数不变化。
- RoundingMode.HALF_UP(四舍五入):四舍五入,保留数字后面第一位是非零即进1。
- RoundingMode.HALF_DOWN(半舍半入):保留数字后面第一位是非零即进1,如果第二位是5则进1。
- RoundingMode.HALF_EVEN(银行家舍入):四舍六入五留双,保留数字后面第一位是非零即进1,如果第二位是5则看第一位,是偶数则进1,否则舍去。
- RoundingMode.UNNECESSARY(必要):如果舍入后的结果不是原数则抛出异常。
以上就是BigDecimal中的八种RoundingMode,每种模式都有其特定的行为和用途。在使用BigDecimal进行高精度计算时,可以根据需要选择合适的舍入模式来保证计算的准确性和精度。
BigDecimal a = new BigDecimal("1.2345");
BigDecimal b = new BigDecimal("3.1415");
// 加法
BigDecimal sum = a.add(b);
// 减法
BigDecimal difference = a.subtract(b);
// 乘法
BigDecimal product = a.multiply(b);
// 除法,指定精度和舍入模式
BigDecimal quotient = a.divide(b, 4, RoundingMode.HALF_UP);
示例:百分数数字转换
将99.99%转换成小数0.9999,再将0.9999转换成99.99
double p = 99.99;
BigDecimal bP = new BigDecimal(String.valueOf(p));
BigDecimal b100 = new BigDecimal(String.valueOf(100));
BigDecimal bigDiv = bP.divide(b100);
double d = bigDiv.doubleValue();
System.out.println(bigDiv);//0.9999
System.out.println(d);//0.9999
BigDecimal dP = new BigDecimal(String.valueOf(d));
BigDecimal s = dP.multiply(b100);
double ss = s.doubleValue();
System.out.println(s);//99.9900
System.out.println(ss);//99.99
比较BigDecimal值
避免使用equals()方法,因为它会比较精度和值。使用compareTo()方法进行值比较:
BigDecimal x = new BigDecimal("1.0");
BigDecimal y = new BigDecimal("1.00");
// 不推荐:false,因为精度不同
boolean eq = x.equals(y);
// 推荐:0,表示值相等
int cmp = x.compareTo(y);
格式化BigDecimal输出
使用DecimalFormat可以控制BigDecimal的输出格式:
BigDecimal value = new BigDecimal("1234.5678");
DecimalFormat df = new DecimalFormat("#,##0.00");
String formatted = df.format(value); // 输出:1,234.57
注意事项
- BigDecimal是不可变对象,每次运算都会产生新对象
- 对于金融计算等需要精确小数的场景,优先使用BigDecimal
- 构造BigDecimal时尽量使用字符串而非float/double字面量
- 运算时明确指定舍入模式,避免出现ArithmeticException

982

被折叠的 条评论
为什么被折叠?



