项目里有图表展示数据的需求,比如[239,213,122,12,321]计算每个数字占总和的百分比,直接四舍五入可能总和不能正好100%
Flutter实现:
print('-----最大余额法-----${maximumBalance([239,213,122,12,321])}');
-----最大余额法-----[26.35%, 23.49%, 13.45%, 1.32%, 35.39%]
import 'package:collection/collection.dart';
/// 最大余额法
List<String> maximumBalance(List<double> data) {
// 总额
double sum = 0;
for (double element in data) {
sum += element;
}
if (sum == 0) {
return [];
}
// 总份额,共4位数
double total = 10000;
// 分配份额
List<double> shareList = data.map((e) => e / sum * total).toList();
// 整数部分
List<int> integerList = shareList.map((e) => e.toInt()).toList();
// 计算整数部分的总和
int shareSum = integerList.reduce((value, element) => value + element);
// 小数部分
List<double> decimalsList = shareList.mapIndexed((index, element) => element - integerList[index]).toList();
// 整数部分总和小于总份额时
while (shareSum < total) {
double max = decimalsList[0];
int maxIndex = 0;
// 找出小数位最大的下标
for (int i = 1; i < decimalsList.length; i++) {
if (decimalsList[i] > max) {
max = decimalsList[i];
maxIndex = i;
}
}
// 小数位最大的加1
integerList[maxIndex] += 1;
// 加1后小数清零,不参与下次比较
decimalsList[maxIndex] = 0;
// 总数也需要加1
shareSum += 1;
}
// 图表数据
List<double> dataList = [];
List<String> legendList = [];
for (int element in integerList) {
double data = element / 100;
dataList.add(data);
legendList.add('${data.toStringAsFixed(2)}%');
}
return legendList;
}