开发了一个项目,涉及到了价格计算的问题,由于之前考虑的不够周全,所有遇到了好多的类型之间计算出现的精度不准的问题,在这和大家分享一下,说的有不对的直接关闭此网页.
//直接用int + double 进行运算,可想而知结局是悲惨的
int g = 2;
double a = 0.01;
double b = 0.05;
double k = g+b+a;
System.out.println("k:" + k);
结果:k:2.0599999999999996
***这个因为如果不同类型的数据进行相加,会将类型统一成一个类型的数据在进行计算,因为double类型的数据占的字节多 所以java编译器会自己帮你把int类型的数据转换成double 类型的数据 然后再实行两个double类型的数据相加***
//当时用float,然后就出现了小数丢失的现像
float d = 0.01f;
float e = 0.05f;
float f = d + e;
System.out.println("f:" + f);
结果:f:0.060000002
//接着换下一个double,当时觉得肯定是可以了,但是........
double a = 0.01;
double b = 0.05;
double c = a + b;
System.out.println("c:" + c);
结果:c:0.060000000000000005
***并不是所有的小数都可以用二进制浮点数来精确表示的
二进制浮点不可能将0.1——或者10的其它任何次负幂——精确表示为一个长度有限的二进制小数 (看下计算机组成原理中的浮点数的表示方法,好象有不同的标准)***
解决的方法可以用BigDecimal类,该类位于java.math包中
基本 加,减,乘,除,保留两位小数,四舍五入等
BigDecimal decimal = new BigDecimal(要计算的参数);
值得注意的是要是想计算的精准一些 ,f要计算的参数最好是字符类型的
类型转换的时候最好用各数据类型包装器,例如:Integer.parseInt(s)等, 像 (int)a 强行转换类型有的时候会有问题
// 相加
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
// 相减
public static double sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
// 相乘
public static double mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 相除,做除法的时候相对的麻烦一点,涉及的多一些
* 提供精确的小数位四舍五入处理。
* @param v1 需要四舍五入的数字
* @param v2 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("此参数错误");
}
BigDecimal one = new BigDecimal(Double.toString(v1));
BigDecimal two = new BigDecimal(Double.toString(v2));
return one.divide(two, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
以上就是本次开发中遇到的BUG, 菜鸟一个努力学习中 , 多多支持…
关注回复【资料】,免费获取架构资料、视频,还有精心整理的面试题