由图框选出来的地方可以看出不一致。
开始以为是js toFixed四舍五入的问题,材料提交计算出来的百分比值是60.824742268041234。toFixed(2)后得到60.82。
写了个递归如下,可以算出60.83
/** * 获取给定精度的数据 * @param {number} num 数字 * @param {number} n 精度 * @return {number} 百分数 */ NumberToFixed(num, n) { let arr = (num + '').split(''); let dian = arr.findIndex(r => r === '.'); let newArr = []; for (let i = 0; i < arr.length; i++) { if (i <= dian + n) { newArr.push(arr[i]); } else { if (arr[i] != 4) { newArr.push(arr[i]); break; } else { newArr.push(arr[i]); } } } // 先过滤数据,变成60.8247,再递归 return this.NumberToFixed2(newArr.join(''), n); }, NumberToFixed2(num, n) { let arr = (num + '').split(''); let dian = arr.findIndex(r => r === '.'); num = Number(num); if (arr.length <= dian + n + 2) { return num.toFixed(n); } else { let newNum = num.toFixed(arr.length - dian - 2); return this.NumberToFixed2(newNum, n); } },
后同事找到echarts算百分比的方法,发现并不是用四舍五入计算的。而是先算出百分比,再乘以10000,向下取整,再相加,总数不等于10000的话, 取出小数最大的索引对应的整数+1,然后将小数置0,将currentSum+1,,再循环 取出小数最大的索引对应的整数+1,然后将小数置0,将currentSum+1,,直到currentSum等于10000.
佩服大神写的代码,思路令人大开眼界。
具体方法如下(修改过)
/** * 获取给定精度的数据,确保valueList中的百分比之和为1 * 采用最大余数法 * @param {number[]} valueList 所有数据的列表 * @param {number} idx 数据的索引 * @param {number} precision 精度 * @return {number} 百分数 */ getPercentWithPrecision(valueList, idx, precision) { if (!valueList[idx]) { return 0; } var sum = valueList.reduce(function(acc, val) { return acc + (isNaN(val) ? 0 : val); }, 0); if (sum === 0) { return 0; } var digits = Math.pow(10, precision); var votesPerQuota = valueList.map(val => { return ((isNaN(val) ? 0 : val) / sum) * digits * 100; }); var targetSeats = digits * 100; var seats = votesPerQuota.map(votes => Math.floor(votes)); var currentSum = seats.reduce(function(acc, val) { return acc + val; }, 0); var remainder = votesPerQuota.map((votes, idx) => votes - seats[idx]); // Has remainding votes. while (currentSum < targetSeats) { // Find next largest remainder. var max = -Infinity; //Number.NEGATIVE_INFINITY; var maxId = null; for (var i = 0, len = remainder.length; i < len; ++i) { if (remainder[i] > max) { max = remainder[i]; maxId = i; } } // Add a vote to max remainder. ++seats[maxId]; remainder[maxId] = 0; ++currentSum; } return seats[idx] / digits; },