情景一
接口字段,Number类型数据失真,解决方法可直接让服务端把字段类型改成String类型即可。
情景二
某些特殊场景,需要保留小数点后9位(及其以上),直接调用Number对象自带的toFixed()函数,会出现小数点后数据失真情况。比如以下这种场景:
当保留小数点后8位时,数据还是正常的,一旦超过8位,即会出现数据失真情况。
解决方案
/*** 精确保留小数(可超过9位)* @param {string} num 原数字(输入数字为字符串类型最佳)* @param {num} digits 保留小数位数* @returns 返回字符串类型处理结果*/toFixedPro(num, digits = 0) {//类型强转let zeroStrNum = String(num);//负数标记let isNegativeNum = false// 判断是否为负数if(zeroStrNum.startsWith('-')){isNegativeNum = truezeroStrNum = zeroStrNum.slice(1)}// 获取小数点位置const dotIndex = zeroStrNum.indexOf('.')// 如果是整数/保留小数位数等于超过当前小数长度if(dotIndex === -1 || (zeroStrNum.length - (dotIndex + 1) <= digits)){// 如果事负数,添加负号zeroStrNum = isNegativeNum ? `-${zeroStrNum}` : zeroStrNum//判断是否添加小数点zeroStrNum = dotIndex === -1 ? `${zeroStrNum}.` : zeroStrNum;//补零处理let repair = digits - zeroStrNum.split('.')[1].length;for(let i = 0; i < repair; ++i){zeroStrNum += '0';}return zeroStrNum;}// 找到需要进行四舍五入的部分let numArr = zeroStrNum.match(/\d/g) || [];numArr = numArr.slice(0, dotIndex + digits + 1)// 核心处理逻辑if (parseInt(numArr[numArr.length - 1], 10) > 4) {// 如果最后一位大于4,则往前遍历+1for (let i = numArr.length - 2; i >= 0; i--) {numArr[i] = String(parseInt(numArr[i], 10) + 1);// 判断这位数字 +1 后会不会是 10if (numArr[i] === '10') {// 10的话处理一下变成 0,再次for循环,相当于给前面一个 +1numArr[i] = '0';} else {// 小于10的话,就打断循环,进位成功break;}}}// 将小数点加入数据numArr.splice(dotIndex, 0, ".")// 处理多余位数numArr.pop()// 如果事负数,添加负号if(isNegativeNum){numArr.unshift("-")}log.debug('处理后数据数组:', numArr);return numArr.join('');},
运行示例
//测试代码let numStr = '123456789.123456789666';console.log('原始数据:', numStr);//123456789.123456789666let resultStr = this.toFixedPro(numStr, 9);console.log('处理结果:', resultStr );//123456789.123456790
至此,结束。