echarts 算百分比与js toFixed算出来的百分比不一致的问题。

 由图框选出来的地方可以看出不一致。

开始以为是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;
        },
原文地址:https://www.cnblogs.com/m7777/p/14944412.html