Calculating number of seats in parliament using d’Hondt’s method

Wikipedia contains an article on d’Hondt’s method for calculating the number of seats given the number of votes for each party. I wrote a short Perl program for its calculation including the case when d’Hondt’s method by its design leads to drawing the lots. Its input contains a list of party names and its corresponding votes. The number of seats is given as parameter -s. This implementation of d’Hondt uses integer division and rounds the division to the lower integer (floor).

#!/usr/bin/perl -W
# Calculate seats in parliament according d'Hondt's method

use strict;
use Getopt::Std;
my %opts = ('d' => 0, 's' => 2);
getopts('ds:',\%opts);
my $s = (($opts{'s'} > 0) ? $opts{'s'} : 2);

my (@F,@votes,@party,@seat,@calc,@divisor,$i,$j,$n,$max,$multi,@drawing);

while (<>) {
        @F = split;
        push @party,$F[0];
        push @votes,$F[1];
        push @calc,$F[1];
}

for ($i=0; $i<=$n; ++$i) {
        ($seat[$i],$divisor[$i]) = (0,1);
}

# $u is used seats so far
for (my $u=0; $u<$s; ++$u) {
        ($max,$j) = ($calc[0],0);       # calculate maximum in @calc
        $drawing[$multi=0] = 0;
        for ($i=1; $i<=$n; ++$i) {
                if ($calc[$i] > $max) {
                        ($max,$j) = ($calc[$i],$i);
                        $drawing[$multi=0] = $i;
                } elsif ($calc[$i] == $max) {
                        $drawing[++$multi] = $i;
                }
        }
        if ($u + $multi >= $s) {
                printf("Drawing of lots for %d seats required for parties:", $s - $u);
                for ($i=0; $i<=$multi; ++$i) {
                        print " $party[$drawing[$i]]";
                }
                print "\n";
                last;
        }
        $seat[$j] += 1;
        $divisor[$j] += 1;      # this is specific for d'Hondt
        $calc[$j] = int($votes[$j] / $divisor[$j]);
}

for ($i=0; $i<=$n; ++$i) {
        print "$party[$i] - $seat[$i]\n";
}

Above Perl code is also in GitHub.

Here are some results.

Test case #1 from Wikipedia where 4 parties compete for 8 seats in parliament:

Party A        100,000
Party B         80,000
Party C         30,000
Party D         20,000

printf "A 100000\nB 80000\nC 30000\nD 20000\n" | dHondt -s8 gives

A - 4
B - 3
C - 1
D - 0

Test case #2 from Bundeswahlleiter with 3 parties again competing for 8 seats:

Party A       10,000
Party B        6,000
Party C        1,500

Running printf "A 10000\nB 6000\nC 1500\n" | dHondt -s8 produces

A - 5
B - 3
C - 0

Test case #3 from R function to calculate the seats in parliament with 5 parties competing for 10 seats:

Party A         448
Party B       7,685
Party C       5,445
Party D         482
Party E       6,266

Running printf "A 448\nB 7685\nC 5445\nD 482\nE 6266\n" | dHondt -s10 gives

A - 0
B - 4
C - 3
D - 0
E - 3

I think the given implementation in R is faulty, although for above example it is correct.

Test case #4 checks the borderline.

Party A       8
Party B       8
Party C       8

Running printf "A 8\nB 8\nC 8\n" | dHondt -s1 gives

Drawing of lots for 1 seats required for parties: A B C
A - 0
B - 0
C - 0

Test case #5 also checks borderline. Input as given in test case #4 but number of seats is 2. Perl program computes

Drawing of lots for 2 seats required for parties: A B C
A - 0
B - 0
C - 0

Some historical notes on d’Hondt. According Friedrich Pukelsheim in his report seen in wahlrecht.de the naming of various methods used for seat allocation are good examples of Stigler’s law of eponymy. D’Hondt’s method was already used by Thomas Jefferson. D’Hondt’s method is also known under the name Hagenbach-Bischoff method.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s