目录
BigDecimal
BigDecimal的常见构造器、常用方法
用法示例
使用规范
在进行浮点型运算时,直接使用“ + - * / ”可能会出现运算结果失真,例如:
System.out.println(0.1 + 0.2);
System.out.println(1.0 - 0.32);
System.out.println(1.015 * 100);
System.out.println(1.301 / 100);
运行结果:
诸如这些情况,就是出现了结果失真的问题。
BigDecimal类就是为了解决这个问题的。
BigDecimal
- 用于解决浮点型运算时,出现结果失真的问题。
BigDecimal的常见构造器、常用方法
构造器 | 说明 |
---|---|
public BigDecimal(double val) 注意:不推荐使用这个 | 将double转换为BigDecimal |
public BigDecimal(String val) | 把string转成BigDecimal |
方法名 | 说明 |
---|---|
public static BigDecimal valueOf(double val) | 转换一个double成BigDecimal |
public BigDecimal add(BigDecimal b) | 加法 |
public BigDecimal subtract(BigDecimal b) | 减法 |
public BigDecimal multiply(BigDecimal b) | 乘法 |
public BigDecimal divide(BigDecimal b) | 除法 |
publicBigDecimal divide(另一个BigDecimal对象,精确几位,舍入模式) | 除法、可以控制精确到小数几位 |
public double doubleValue() | 将BigDecimal转换为double |
用法示例
public class Test {
public static void main(String[] args) {
double a = 0.1;
double b = 0.2;
// BigDecimal a1 = new BigDecimal(Double.toString(a));
// BigDecimal b1 = new BigDecimal(Double.toString(b));
//推荐使用以下方式,把小数转换成字符串再得到BigDecimal对象来使用(更简洁)
BigDecimal a1 = BigDecimal.valueOf(a);
BigDecimal b1 = BigDecimal.valueOf(b);
BigDecimal c1 = a1.add(b1);
System.out.println(c1);
}
}
运行结果:
(没有出现运算结果失真)
其他方法
public class Test {
public static void main(String[] args) {
double a = 0.1;
double b = 0.2;
// BigDecimal a1 = new BigDecimal(Double.toString(a));
// BigDecimal b1 = new BigDecimal(Double.toString(b));
//推荐使用以下方式,把小数转换成字符串再得到BigDecimal对象来使用(更简洁)
BigDecimal a1 = BigDecimal.valueOf(a);
BigDecimal b1 = BigDecimal.valueOf(b);
BigDecimal c1 = a1.add(b1);
System.out.println(c1);
BigDecimal c2 = a1.subtract(b1); //减法
BigDecimal c3 = a1.multiply(b1); //乘法
BigDecimal c4 = a1.divide(b1); //除法
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
}
}
运行结果:
注意:对于除法,如果无法除尽,会因无法确定精度而报错。
public class Test {
public static void main(String[] args) {
BigDecimal i = BigDecimal.valueOf(0.1);
BigDecimal j = BigDecimal.valueOf(0.3);
BigDecimal k = i.divide(j); //除不尽
}
}
解决办法:
public class Test {
public static void main(String[] args) {
BigDecimal i = BigDecimal.valueOf(0.1);
BigDecimal j = BigDecimal.valueOf(0.3);
// BigDecimal k = i.divide(j); //除不尽
BigDecimal k = i.divide(j,2, RoundingMode.HALF_UP); //这里的RoundingMode.HALF_UP是一个枚举类里的常量,代表四舍五入
System.out.println(k);
}
}
这样运行结果就正常了,(保留两位小数) 但是一般还是用double来解决这种问题
再来示例一下,把BigDecimal对象转换成double类型的数据
public class Test {
public static void main(String[] args) {
BigDecimal i = BigDecimal.valueOf(0.1);
BigDecimal j = BigDecimal.valueOf(0.3);
// BigDecimal k = i.divide(j); //除不尽
BigDecimal k = i.divide(j,2, RoundingMode.HALF_UP); //这里的RoundingMode.HALF_UP是一个枚举类里的常量,代表四舍五入
//把BigDecimal对象转换成doubLe类型的数据
double rs = k.doubleValue();
System.out.println(rs);
}
}
运行结果: 已转换为double类型
使用规范
提及其中的一点: (取自Java开发手册)
禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象。
说明:BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。
如:BigDecimal g = new BigDecimal(0.1F); 实际的存储值为:0.10000000149
正例 优先推荐入参为String的构造方法去,或使用BigDecinal的valueOf方法,此方法内部其实执行了Double的toString,而Double的toString按double的实际能表达的精度对尾数进行了截断。
END
学习自:黑马程序员——JavaSE课程