最大余额法,解决百分比计算相加不等于100%(扇形/饼图百分比使用的此算法)

在开发项目的过程中有时候需要进行计算百分比,例如计算饼状图百分比。有时候在计算的过程中常规四舍五入计算会发生所有计算的值相加不等于100%的情况

这是 get_percent_value 函数的 JavaScript 版本:

javascript 复制代码
/**
 * 最大余额法,解决百分比计算相加不等于100%(扇形/饼图百分比使用的此算法)
 * @param {Array} valueList 二维数组 [{value: 1}, {value: 2}, {value: 3}]
 * @param {string} contKey 要统计的字段
 * @param {number} precision 精度(默认为2保留百分比格式的两位小数)
 * @param {string} percentKey 百分比键名
 * @param {boolean} format 是否需要返回格式化后百分比格式,false则返回小数
 * @return {Array}
 */
function getPercentValue(valueList, contKey, precision = 2, percentKey = 'percent', format = true) {
    if (valueList.length === 0) {
        return [];
    }
    
    // 求和
    const sum = valueList.reduce((acc, item) => acc + item[contKey], 0);
    
    // 如果总和为0,直接返回
    if (sum === 0) {
        return valueList.map(item => ({
            ...item,
            [percentKey]: format ? '0%' : 0
        }));
    }
    
    // 计算精度
    const digits = Math.pow(10, precision);
    let currentSum = 0;
    let remainder = [];

    // 计算每个项目的整数和余数部分
    valueList.forEach((item, index) => {
        const votesPerQuota = (item[contKey] / sum) * digits * 100;
        const integerPart = Math.floor(votesPerQuota);
        valueList[index].integer = integerPart;
        remainder[index] = votesPerQuota - integerPart;
        currentSum += integerPart;
    });

    const targetSeats = digits * 100;

    // 找到最大余数并加1,直到总数达到目标
    while (currentSum < targetSeats) {
        const maxIndex = remainder.indexOf(Math.max(...remainder));
        valueList[maxIndex].integer++;
        remainder[maxIndex] = -1; // 确保该余数不会再被选中
        currentSum++;
    }

    // 生成最终的百分比值
    valueList.forEach(item => {
        item[percentKey] = (item.integer / targetSeats).toFixed(precision + 2);
        if (format) {
            item[percentKey] = (parseFloat(item[percentKey]) * 100).toFixed(precision) + '%';
        }
        delete item.integer;
    });

    return valueList;
}

// 使用示例
const data = [
    { value: 3 },
    { value: 3 },
    { value: 3 }
];

const rateData = getPercentValue(data, 'value', 2, 'percent', false);
console.log(rateData);

说明:

  • reduce 用于求和。
  • Math.floor 用于获取整数部分。
  • Math.maxindexOf 用于找到最大余数的位置。
  • toFixed 保留指定的小数位数。

你可以通过 getPercentValue 函数来计算各项的百分比,并决定是否返回格式化的百分比形式。

相关推荐
小曲曲43 分钟前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
学不会•2 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS3 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
网易独家音乐人Mike Zhou3 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
活宝小娜4 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点4 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow4 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o4 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic5 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā5 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue