Ok, so you have coded a voting system and need to calculate the voting percentage to display something like:
- Messi50%
- Ronaldo50%
Ok, cool, so we count the number of votes for each option, then divide by the total number of votes. Easy.
- Dogs1 vote33%
- Cats2 votes66%
Oops, the votes do not add up to 100%, which looks weird, so I guess rounding down those fractions won’t cut it. Let’s do the actual rounding.
> Math.round(2/3 * 100)
67
> Math.round(1/3 * 100)
33
- Dogs1 vote33%
- Cats2 votes67%
Nice! Let’s try the other case.
- Terran1 vote33%
- Zerg1 vote33%
- Protoss1 vote33%
Well, the sum is not 100%, but it is a draw, so it probably works. But what if:
- Swimming1 vote17%
- Running1 vote17%
- Cycling4 votes67%
> 17 + 17 + 67
101
Not good, 101% total is not something your election committee will be happy about. Perhaps the issue can be solved if we don’t round up to whole numbers? Let’s try adding another decimal unit:
> Math.round(1/6 * 1000)/10 +
Math.round(1/6 * 1000)/10 +
Math.round(4/6 * 1000)/10
100.1
Arguably better, but not perfect.
At this point, you Google up or come up with the Hare-Niemeyer (or largest remainder) method. Essentially, you need to calculate percentages, take the integer parts (i.e., use the floor() function), and then award the percentages remaining from 100, starting with the largest remainders. In the example above, it still fails, though. All options are tied with 0.666... remainders.
- Swimming1 vote16.666%
- Running1 vote16.666%
- Cycling4 votes66.666%
If we drop the remainders, we end up with the sum of 98%.
- Swimming1 vote16%
- Running1 vote16%
- Cycling4 votes66%
Hare-Niemeyer is designed for awarding seats in the representative assemblies based on the number of votes cast. It suggests random allocation or drawing lots in the case of draws. In a poll the reader can see the vote counts, however, and two options with the same number of votes showing different percentages looks like a bug. So here is the one that works best.
Keep the ties, then fill up to 100%
Instead of awarding the leftover percentages one option at a time, award them to whole groups of tied options. Every option shows its percentage either rounded down or rounded up, and:
- Options with the same number of votes always show the same percentage.
- An option never shows a smaller percentage than an option with fewer votes.
- The total gets as close to 100% as rules 1 and 2 allow, and never goes above it.
- If there are several ways to get there, round up the options with the largest remainders.
In the “Swimming, Running, Cycling” example, there are 2 percentage points left after rounding down. Cycling alone can’t take both, but the Swimming and Running pair can:
- Swimming1 vote17%
- Running1 vote17%
- Cycling4 votes66%
When there is no way to hand out the leftover without breaking a tie, like in the Terran, Zerg, Protoss draw, the total stays a little under 100%, which is the honest result.
Try to break it yourself:
- Alphavote17%16.67%
- Betavote17%16.67%
- Gammavotes66%66.67%