How to Display Vote Percentage

Ok, so you have coded a voting system and need to calculate the voting percentage to display something like:

  • Messi
    50%
  • Ronaldo
    50%

Ok, cool, so we count the number of votes for each option, then divide by the total number of votes. Easy.

  • Dogs
    1 vote
    33%
  • Cats
    2 votes
    66%

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
  • Dogs
    1 vote
    33%
  • Cats
    2 votes
    67%

Nice! Let’s try the other case.

  • Terran
    1 vote
    33%
  • Zerg
    1 vote
    33%
  • Protoss
    1 vote
    33%

Well, the sum is not 100%, but it is a draw, so it probably works. But what if:

  • Swimming
    1 vote
    17%
  • Running
    1 vote
    17%
  • Cycling
    4 votes
    67%
> 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.

  • Swimming
    1 vote
    16.666%
  • Running
    1 vote
    16.666%
  • Cycling
    4 votes
    66.666%

If we drop the remainders, we end up with the sum of 98%.

  • Swimming
    1 vote
    16%
  • Running
    1 vote
    16%
  • Cycling
    4 votes
    66%
Total 98%

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:

  1. Options with the same number of votes always show the same percentage.
  2. An option never shows a smaller percentage than an option with fewer votes.
  3. The total gets as close to 100% as rules 1 and 2 allow, and never goes above it.
  4. 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:

  • Swimming
    1 vote
    17%
  • Running
    1 vote
    17%
  • Cycling
    4 votes
    66%
Total 100%

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:

  • Alpha
    vote
    17%
    16.67%
  • Beta
    vote
    17%
    16.67%
  • Gamma
    votes
    66%
    66.67%
Total 100%
Vitalii

Hi. I'm Vitalii.

I’m a software developer, technical manager and solo entrepreneur. I have been building software products all my life. I am offering CTO as a Service at many-to-many.

Contact me

Let me know what are you looking for. I will reach out to you via the provided email with quote and follow up questions. Alternatively, book a call or reach me directy by email hello@manytomany.co.

Sending...
We have received your message and will respond shortly. Thank you!

Or using your preferred messaging app: