那什麽是最大余額方法呢?以下概念摘自維基百科,有壹點晦澀難懂,下壹節通過具體例子分析壹下就好懂多了 最大余額方法 (英文:Largest Remainder Method)又稱數額制,是比例代表制投票制度下,壹種議席分配的方法,相對於最高均數方法。
透過最大余額方法,候選人須以名單參選,每份名單的人數最多可達至相關選區內的議席數目。候選人在名單內按優先次序排列。選民投票給壹份名單,而不是個別候選人。投票結束後,把有效選票除以數額(quota,見下)。壹份名單每取得數額1倍的票數,便能獲分配壹個議席。每份名單的候選人按原先訂立的順序當選。
如此類推、將議席分配至每份名單的余額,均比數額為低的時候,則從最大余額者順序分配余下議席;最大余額方法因而得名。
假設選舉投票人次100,000,分配10個議席。選舉結果:
黑爾數額為黑爾數額為 100000/10 = 10000張選票,即每張名單每獲得10,000張選票,便能首先得到1個議席:
因此,名單丙、丁、戊各得1席,名單己得4席。余下3席,則對比各個余額。其中名單乙、戊、己的余額最大,因此分別獲選其余3席。
換言之,在最大余額方法之下,名單乙、丙、丁各得1席,名單戊得2席,名單己得5席。
看了以上的圖應該對最大余額法有壹點的了解了。那我們來看看源碼是如何通過最大余額法來進行百分比分配的。
以下通過壹組例子數據來
數據值列表:[2, 4, 3]
精度:2(代表百分數的值最多保留2位小數)
期望結果: [ 22.22, 44.45, 33.33 ]
/**
*
* 給定壹個精度值,計算某壹項在壹串數據中占據的百分比,確保百分比總和是1(100%)
* 使用最大余額法
* @param {Array.} valueList a list of all data 壹列數據
* @param {number} idx index of the data to be processed in valueList 索引值(數組下標)
* @param {number} precision integer number showing digits of precision 精度值
* @return {number} percent ranging from 0 to 100 返回百分比從0到100
*/
function 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
}
console.log('sum', sum)
// sum 9
var digits = Math.pow(10, precision)// digits 100
console.log('digits', digits)
var votesPerQuota = valueList.map(function (val) {
return (isNaN(val) ?0 : val) / sum * digits *100 // 擴大比例,這樣可以確保整數部分是已經確定的議席配額,小數部分是余額
})
console.log('votesPerQuota', votesPerQuota)
// votesPerQuota [ 2222.222222222222, 4444.444444444444, 3333.333333333333 ] 每壹個項獲得的議席配額,整數部分是已經確定的議席配額,小數部分是余額
var targetSeats = digits *100 // targetSeats 10000 全部的議席
console.log('targetSeats', targetSeats)
var seats = votesPerQuota.map(function (votes) {
// Assign automatic seats.
return Math.floor(votes)
})
console.log('seats', seats)
// seats [ 2222, 4444, 3333 ] 獲取配額的整數部分
var currentSum = seats.reduce(function (acc, val) {
return acc + val
}, 0)
console.log('currentSum', currentSum)
// 9999 表示已經配額了9999個議席,還剩下壹個議席
var remainder = votesPerQuota.map(function (votes, idx) {
return votes - seats[idx]
})
console.log('remainder', remainder)
// [ 0.2222222222221717, 0.4444444444443434, 0.33333333333303017 ]得到每壹項的余額
// Has remainding votes. 如果還有剩余的坐席就繼續分配
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
}
}
// max: 0.4444444444443434, maxId 1
// Add a vote to max remainder.
++seats[maxId]// 第二項,即4的占比的坐席增加1
remainder[maxId] =0
++currentSum// 總的已分配的坐席數也加1
}
return seats[idx] / digits
}
最大余額法