起因是在前端计算金额的时候,导致和总金额不等:
1.计算:"246409.2", "328545.6", "164272.8", "82136.4"的和,发现他的结果是
System.out.println((new BigDecimal(246409.2+328545.6+164272.8+82136.4)));
//输出结果:
821364.000000000116415321826934814453125
跟想象的不一样,其实相当然以为是821364.0
2.又想了一种计算方式:
System.out.println((246409.2+328545.6+164272.8+82136.4));
//输出结果
821364.0000000001
3.再换一种(这里想的是前端直接+的话可能是字符串拼接了,所以×1)
System.out.println((246409.2*1+328545.6*1+164272.8*1+82136.4));
//输出结果
821364.0000000001
4.又试了一种发现这个计算合理那就是BigDecimal类
String [] numbers = {"246409.2", "328545.6", "164272.8", "82136.4"};
//求和
BigDecimal sum = BigDecimal.ZERO;
for (String number : numbers) {
sum = sum.add(new BigDecimal(number));
}
System.out.println("总和是:" + sum);
//输出结果是
总和是:821364.0
这些都是由于精度问题导致的,查了一下,在做运算的时候前端的话会,(java也是二进制计算的,具体的话懒得知道)
IEEE 754规定了四种表示浮点数值的方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80位实现),js则是64位
总之就是转成2进制再计算,比较精确,一般科学、数学需要用它比较合适,向我们正常计算。尤其这个算金额的时候大可不必
5.下面给出自己按照小数点位数的计算精度问题:
public static void main(String[] args) {
String [] numbers = {"246409.2", "328545.60", "164272.8", "82136.4"};
round(numbers);
}
//用于精度问题求和的通用方法
public static void round(String[]numbers) {
//定义一个最长的小数位数
int maxLen = 0;
//求和
BigDecimal sum = BigDecimal.ZERO;
// 遍历这个数组
for (String number : numbers) {
//取小数点后几位找最长的是多少位
int len = number.indexOf(".");
if (len != -1) {
len = number.substring(len + 1).length();
}
//比较这组数的最长的精度的最大值
if (len > maxLen) {
maxLen = len;
}
sum = sum.add(new BigDecimal(number));
}
//将这组数据求和再取最大长度的小数位数
System.out.println(sum.setScale(maxLen, BigDecimal.ROUND_HALF_UP));
}
//输出结果
821364.00
这种方法就是找出这组数据小数点最长的位数给求和结果取保留位数,看BigDecimal的底层, 脑袋大,不想看了,反正我试了也是给定几位,计算之后也是按照位数最长的来的,等待大神有缘人讲讲吧