浮点型计算会有精度丢失问题,解决思路V1版:
1、把浮点型 转换为 int整形计算 在除以 倍数
比如: 0.1+0.02=(0.1*100+0.02*100)/100
2、倍数 怎么取
小数点后的位数长度就是 倍数,可把 浮点参数 当成字符串,然后利用splic字符串处理函数来用.分割为数组,第二个数组中的字符串 就是 小数点后的 字符串,调用length就可以知道 倍数长度。
// 浮点型 加法 实现,也同时支持整形相加
// 有缺陷,1.001*1000也会有精度丢失问题
function addFloatV1(){
// 取参数的最小值,拿到最小值计算 最小值的 小数点后的 位数 来获取倍数
if (!arguments){
return undefined;
}
var minVal = Math.min(...arguments).toString(); // 取最小值
var minValBs = 1; // 倍数
if (minVal.indexOf('.') === 1) {
var minValLength = minVal.split('.')[1].length; // 取最小值小数位数
minValBs = Math.pow(10,minValLength);// 幂运算 计算倍数
}
// 循环参数,把参数都*100 然后再相加。
// 循环完成后,把 整形部分的sum值 再除以 刚刚的倍数值
var sum = 0;
for(var i=0;i<arguments.length;i++){
sum += arguments[i]*minValBs;
}
return sum/minValBs;
}
addFloatV1(1.01,1.02)
v1版本问题:1.001*1000精度丢失问题会存在,部分小数计算仍然有问题。
浮点型计算会有精度丢失问题,解决思路V2版(升级版本):
在V1版基础上,解决小数*倍数也会丢失精度问题,比如1.001*1000精度丢失
所以,最终的倍数取决于是整数的length长还是小数位数的length长,然后小数部分去掉小数点转化为整数,然后整数部分,用倍数的位数和整数的位数计算位数差值,再用整数部分乘以差值倍数来计算。最终的整数sum和在除以倍数,计算出最终结果。
// 浮点型 加法 实现,也同时支持整形相加
// 改造后
function addFloatV2(){
// 取参数的最小值,拿到最小值计算 最小值的 小数点后的 位数 来获取倍数
if (!arguments){
return undefined;
}
var minVal = Math.min(...arguments).toString(); // 取最小值
var minValBs = 1; // 倍数
var jsValLength = 0;// 计算位数
if (minVal.indexOf('.') === 1) {
// 取最小值小数位数
jsValLength = minVal.split('.')[1].length>0?minVal.split('.')[1].length:0;
}
var maxVal = Math.max(...arguments).toString(); // 取最大值
if(maxVal.indexOf('.') === -1 && maxVal.length>jsValLength ){
jsValLength = maxVal.length;
}
minValBs = Math.pow(10,jsValLength);// 幂运算 计算倍数
// 循环参数,把参数都*100 然后再相加。
// 循环完成后,把 整形部分的sum值 再除以 刚刚的倍数值
var sum = 0;
for(var i=0;i<arguments.length;i++){
var _v = arguments[i];
var _vStr = arguments[i].toString();
var _vBsc = 1;
if(_vStr.indexOf('.') === 1) {
var _vInt = parseInt(_vStr.replace('.',''));
// 取最小值小数位数
var _vLength= _vStr.split('.')[1].length>0?_vStr.split('.')[1].length:0;
// 倍数差,就是当前浮点数要乘以的倍
var _vBs = Math.pow(10,jsValLength - _vLength);
sum+=_vInt *_vBs;
} else {
var _vLength = _vStr.length>1?_vStr.length:0;
// 倍数差,就是当前浮点数要乘以的倍
var _vBs = Math.pow(10,jsValLength);
sum += _v*_vBs;
}
}
return sum/minValBs;
}
addFloatV2(1.001,2.0)
展示结果:目前测试了几个都正常,如有问题,请反馈