核心内容摘要
17c.一起草:点燃灵感,共绘蓝图的奇遇
问题前端在处理后端接口返回的列表数据进行表尾合计行统计由于返回的金额不固定有小数整数大数值等等会出现累计计算数值精度丢失的问题导致页面数据看起来是错的。
原因在JavaScript中Number.MAX_SAFE_INTEGER是一个常量其值为90071992547409912^53 - 1代表JavaScript中可以安全表示的最大整数。
这意味着任何大于Number.MAX_SAFE_INTEGER的整数在进行数学运算时可能会失去精度因为JavaScript使用IEEE 754标准的64位浮点数表示数字其中包括一个符号位、11位指数位和52位尾数位。
重写el-table 表尾合计行方法template div classtable-container el-table :datatableData show-summary :summary-methodgetSummaries stylewidth: 100% el-table-column propid labelID width120/el-table-column el-table-column propmonth label月份 width120/el-table-column el-table-column propname label姓名/el-table-column el-table-column propamount1 label整数金额 width120/el-table-column el-table-column propamount2 label小数金额 width120/el-table-column el-table-column propamount3 label混合金额 width200/el-table-column /el-table /div /template script export default { name: TableComponent, data() { return { tableData: [ { id: 12987122, month:
, name: 王小虎, amount1: 234, amount2:
2, amount3:
11 }, { id: 12987123, month:
, name: 王小虎, amount1: 165, amount2:
43, amount3:
88 }, { id: 12987124, month:
, name: 王小虎, amount1: 324, amount2:
9, amount3: 2 }, { id: 12987125, month:
, name: 王小虎, amount1: 621, amount2:
2, amount3: 123456789123456789 }, { id: 12987126, month:
, name: 王小虎, amount1: 539, amount2:
1, amount3: 887654321987654321 } ] }; }, methods: { getSummaries(param) { const { columns, data } param; const sums []; columns.forEach((column, index) { if (index
{ sums[index] 合计; return; } const values data.map(item Number(item[column.property])); if (column.property amount
{ // 对amount3字段进行高精度计算 const total this.calculateHighPrecisionSum(data.map(item item.amount
); sums[index] total; } else if (!values.every(value isNaN(value))) { const precisions []; let notNumber true; values.forEach(value { if (!isNaN(value)) { notNumber false; const decimal value.toString().split(.)[1]; precisions.push(decimal ? decimal.length :
; } }); if (!notNumber) { const precision Math.max(...precisions); sums[index] values.reduce((prev, curr) { const value Number(curr); if (!isNaN(value)) { return parseFloat((prev value).toFixed(Math.min(precision,
)); } else { return prev; } },
; } else { sums[index] N/A; } } else { sums[index] N/A; } }); return sums; }, // 高精度计算方法处理大数和小数的精确相加 calculateHighPrecisionSum(amounts) { if (!amounts || amounts.length
return 0; // 使用数组来存储每一位数字从低位到高位 let result []; let maxDecimalPlaces 0; // 先确定最大的小数位数 amounts.forEach(amount { const parts amount.split(.); if (parts.length
{ maxDecimalPlaces Math.max(maxDecimalPlaces, parts[1].length); } }); // 将所有数字转换为整数进行计算乘以10^maxDecimalPlaces const integers amounts.map(amount { const parts amount.split(.); let integerPart parts[0]; let decimalPart parts[1] || ; // 补齐小数位 while (decimalPart.length maxDecimalPlaces) { decimalPart 0; } return integerPart decimalPart; }); // 从右到左逐位相加 let carry 0; let maxLength Math.max(...integers.map(num num.length)); // 补齐位数 for (let i 0; i integers.length; i) { while (integers[i].length maxLength) { integers[i] 0 integers[i]; } } // 逐位相加 for (let i maxLength - 1; i 0; i--) { let sum carry; for (let j 0; j integers.length; j) { sum parseInt(integers[j][i] ||
; } result.unshift(sum %
; carry Math.floor(sum /
; } // 处理最后的进位 while (carry
{ result.unshift(carry %
; carry Math.floor(carry /
; } // 转换回小数形式 let resultStr result.join(); // 如果需要小数点插入小数点 if (maxDecimalPlaces
{ if (resultStr.length maxDecimalPlaces) { // 如果结果长度小于小数位数前面补0 while (resultStr.length maxDecimalPlaces
{ resultStr 0 resultStr; } } const decimalIndex resultStr.length - maxDecimalPlaces; resultStr resultStr.substring(0, decimalIndex) . resultStr.substring(decimalIndex); // 去除末尾多余的0 resultStr resultStr.replace(/\.?0$/, ); // 如果小数点在最后去掉小数点 resultStr resultStr.replace(/\.$/, ); } // 去除开头的0但保留至少一个数字 // 页面eslint校验报错可删除 resultStr resultStr.replace(//, ) || 0; return resultStr; } } }; /script style scoped .table-container { padding: 20px; background-color: #fff; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0,
0.