Skip to content

Instantly share code, notes, and snippets.

@MrZhouZh
Created April 16, 2024 02:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MrZhouZh/b396a14f5390e3c5d14dd63788f390b2 to your computer and use it in GitHub Desktop.
Save MrZhouZh/b396a14f5390e3c5d14dd63788f390b2 to your computer and use it in GitHub Desktop.
席位分配-最大余数法
/**
* 议会席位分配
* echarts source code: https://github.com/apache/echarts/commit/fa8db37e5e11b74cbe6e377399c1bb49b8847704
* echarts issues: https://github.com/apache/echarts/issues/5850
* Ovilia fix: http://zhangwenli.com/blog/2017/06/13/pie-percentage
* wiki 最大余数法: https://en.wikipedia.org/wiki/Largest_remainder_method
*/
function getPercentWithPrecision(valueList = [], idx, precision) {
var sum = valueList.reduce((acc, val) => acc + val, 0)
if (sum === 0) return 0
var digits = Math.pow(10, precision)
var votesPerQuota = valueList.map((value) => value / sum * digits * 100)
var targetSeats = digits * 100;
var seats = votesPerQuota.map((votes) => Math.floor(votes))
var currentSum = seats.reduce((acc, val) => acc + val, 0)
var remainder = votesPerQuota.map((votes, idx) => votes - seats[idx])
while (currentSum < targetSeats) {
// Find next largest remainder.
var max = 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
}
getPercentWithPrecision([50.5, 49.5], 0, 0) === 51;
getPercentWithPrecision([50.5, 49.5], 1, 0) === 49;
getPercentWithPrecision([12.34, 34.56, 53.1], 0, 1) === 12.3;
getPercentWithPrecision([12.34, 34.56, 53.1], 1, 1) === 34.6;
getPercentWithPrecision([12.34, 34.56, 53.1], 2, 1) === 53.1;
getPercentWithPrecision([1.678, 4.783, 2.664, 0.875], 0, 0) === 17;
getPercentWithPrecision([1.678, 4.783, 2.664, 0.875], 1, 0) === 48;
getPercentWithPrecision([1.678, 4.783, 2.664, 0.875], 2, 0) === 26;
getPercentWithPrecision([1.678, 4.783, 2.664, 0.875], 3, 0) === 9;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment