在开发项目的过程中有时候需要进行计算百分比,例如计算饼状图百分比。有时候在计算的过程中常规四舍五入计算会发生所有计算的值相加不等于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.max
和indexOf
用于找到最大余数的位置。toFixed
保留指定的小数位数。
你可以通过 getPercentValue
函数来计算各项的百分比,并决定是否返回格式化的百分比形式。