, 3 min read
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.