Underscore Pi
This clever program written by Brian Westley calculates π by looking at its own area. It is one of the winning entries of IOCCC in 1988.
int F=00,OO=00;
Getting it to run
Because of an unusual use of the preprocessor, the program will not give correct results when compiled with modern gcc.
% gcc ./westley.c && ./a.out
(...warnings omitted)
0.250
One of the solutions is to use the -traditional-cpp
parameter for gcc
, as follows:
% gcc -traditional-cpp ./westley.c && ./a.out
(...warnings omitted)
3.141
Here we have it, a nice approximation of π. But where do we get this value from?
How does it work?
We can ask gcc
to perform only the pre-processing and not the actual compilation, by using the -E
switch:
% gcc -traditional-cpp -E ./westley.c > expanded.c
This gives us a better view on the code, specifically the F_OO
function. The first line of the function shows us that the chains of minuses and underscores have been turned into something like this (newlines added for clarity):
-F<00||--F-OO--;
--F<00||--F-OO--;
--F<00||--F-OO--;
--F<00||--F-OO--;
We know that every _
is expanded by the preprocessor to -F<00||--F-OO--;
. The trick used here is that a minus before an underscore, -_
, would change the expression to say --F<00||--F-OO--;
, changing the negation into a pre-decrement.
The effect of the code above would be one decrement of OO
and four decrements of F
, as follows:
-F < 00 || --F-OO--;
would first check if the negation of F
is less than zero. F
has the value of zero at the beginning, so the condition is false. Therefore, the second part is evaluated, decrementing both F
and OO
. Now, both F
and OO
are equal -1
.
--F < 00 || --F-OO--;
would first decrement F
, and then check if it's less than zero. The condition is true now and the second part is not evaluated, so now F
equals -2
and OO
still equals -1
.
Examining the code further, it is easy to notice that OO
is decremented for every line and F
for every occurrence of an underscore in the code. It is easy to see now that F
is the calculated area of the circle and OO
is the diameter.
Now the code can compute the approximate value of π, from the calculated area and diameter of the circle:
;
A bit of math
The formula used here derived from the one for calculating a circle area from its diameter:
$$ r = \frac{d}{2} $$
$$ A = \pi r^{2} = \pi \big ( \frac{d}{2} \big) ^{2} = \pi \frac{d^2}{4} $$
Dividing both sides by \( \frac{d^{2}}{4} \), we get:
$$ \pi = A \frac{4}{d^{2}} $$
An exercise for the reader
What would happen if you make the circle in the code bigger?