less_retarded_wiki/pi.md
2022-12-17 13:14:37 +01:00

9.5 KiB

Pi

Pi is one of the most important and famous numbers, equal to approximately 3.14, most commonly defined as the ratio of a circle's circumference to its diameter (but also definable in other ways). It is one of the most fundamental mathematical constants of our universe and appears extremely commonly in mathematics, nature and, of course, programming. When written down in traditional decimal system, its digits go on and on without end and show no repetition or simple pattern, appearing "random" and chaotic -- as of 2021 pi has been evaluated by computers to 62831853071796 digits. In significance and properties pi is similar to another famous number: e.

Pi is a real transcendental number, i.e. simply put it cannot be defined by a "simple" equation (it is not a root of any polynomial equation). As a transcendental number it is also an irrational number, i.e. it cannot be written as an integer fraction. Mathematicians nowadays define pi via the period of the exponential function rather than geometry of circles. If we stick to circles, it is interesting that in non-Euclidean geometry the value of "pi" could be measured to different values (if we draw a circle on an equator of a ball, its circumference is just twice its diameter, i.e. "pi" would be measured to be just 2, reveling the curvature of space).

Pi to 100 decimal digits is:

3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679...

Pi to 100 binary fractional digits is:

11.001001000011111101101010100010001000010110100011000010001101 001100010011000110011000101000101110000...

Some people memorize the digits of pi for fun and competition, the world record as of 2022 is 70030 memorized digits.

PI IS NOT INFINITE. Soyence popularizators and nubs often say shit like "OH LOOK pi is so special because it infiniiiiiite". Pi is completely finite with an exact value that's not even greater than 4, what's infinite is just its expansion in decimal (or similar) numeral system, however this is nothing special, even numbers such as 1/3 have infinite decimal expansion -- yes, pi is more interesting because its decimal digits are non-repeating and appear chaotic, but that's nothing special either, there are infinitely many numbers with the same properties and mysteries in this sense (most famously the number e but besides it an infinity of other no-name numbers). The fact we get an infinitely many digits in expansion of pi is given by the fact that we're simply using a system of writing numbers that is made to handle integers and simple fractions -- once we try to write an unusual number with our system, our algorithm simply ends up stuck in an infinite loop. We can create systems of writing numbers in which pi has a finite expansion (e.g. base pi or a base with varying radix fractions), in fact we can already write pi with a single symbol: pi. So yes, pi digits are interesting, but they are NOT what makes pi special among other numbers.

Additionally contrary to what's sometimes claimed it is also unproven (though believed to be true), whether pi in its digits contains all possible finite strings -- note that the fact that the series of digits is infinite doesn't alone guarantee this (as e.g. the infinite series 010011000111... also doesn't contain any possible combination of 1s and 0s). This would hold if pi was normal, but again, there are many other such numbers.

What makes pi special then? Well, mostly its significance as one of the most fundamental constants that seems to appear extremely commonly in math and nature, it seems to stand very close to the root of description of our universe -- not only does pi show that circles are embedded everywhere in nature, even in very abstract ways, but we find it in Euler's identity, one of the most important equations, it is related to complex exponential and so to Fourier transform, waves, oscillation, trigonometry (sin, cos, ...) and angles (radians use pi), it even starts appearing in number theory, e.g. the probability of two numbers being relative primes is 6/(pi^2), and so on.

Approximations And Programming

Evaluating many digits of pi is mathematically interesting, programs for computing pi are sometimes used as CPU benchmarks. There are programs that can search for a position of arbitrary string encoded in pi's digits. However in practical computations we can easily get away with pi approximated to just a few decimal digits, you will NEVER need more than 20 decimal digits, not even for space flights (NASA said they use 15 places).

An ugly engineering approximation that's actually usable sometimes (e.g. for fast rough estimates with integer-only hardware) is just (infamously almost made the legal value of pi by the so called Indiana bill in 1897)

pi ~= 3

A simple fractional approximation (correct to 6 decimal fractional digits) is

pi ~= 355/113

Such a fraction can again be used even without floating point -- let's say we want to multiply number 123 by pi, then we can use the above fraction and compute 355/113 * 123 = (355 * 123) / 113.

Leibnitz formula for pi is an infinite series that converges to the value of pi, however it converges very slowly { Quickly checked, after adding million terms it was accurate to 5 decimal fractional places. ~drummyfish }. It goes as

pi = 4 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + ...

Nilakantha Series converges much more quickly { After adding only 1000 terms the result was correct to 9 decimal fractional places for me. ~drummyfish }. It goes as

pi = 3 + 4/(2 * 3 * 4) + 4/(4 * 5 * 6) + 4/(6 * 7 * 8) + ...

A simple algorithm for computing approximate pi value can be based on approach used in further history: approximating a circle with many-sided regular polygon and then computing the ratio of its circumference to diameter -- as a diameter here we can take the average of the "big" and "small" diameter of the polygon. For example if we use a simple square as the polygon, we get pi ~= 3.31 -- this is not very accurate but we'll get a much higher accuracy as we increase the number of sides of the polygon. In 15th century pi was computed to 16 decimal digits with this method. Using inscribed and circumscribed polygons we can use this to get lower and upper bounds on the value of pi.

Another simple approach is monte carlo estimation of the area of a unit circle -- by generating random (or even regularly spaced) 2D points (samples) with coordinates in the range from -1 to 1 and seeing what portion of them falls inside the circle we can estimate the value of pi as pi = 4 * x/N where x is the number of points that fall in the circle and N the total number of generated points.

Spigot algorithm can be used for computing digits of pi one by one, without floating point. Bailey-Borwein-Plouffe formula (discovered in 1995) interestingly allows computing Nth hexadecimal (or binary) digit of pi, WITHOUT having to compute previous digits (and in a time faster than such computation would take). In 2022 Plouffe discovered a similar formula for computing Nth decimal digit.

The following is a C implementation of the Spigot algorithm for calculating digits of pi one by one that doesn't need floating point or special arbitrary length data types, adapted from the original 1995 paper. It works on the principle of converting pi to the decimal base from a special mixed radix base 1/3, 2/5, 3/7, 4/9, ... in which pi is expressed just as 2.22222... { For copyright clarity, this is NOT a web copy paste, it's been written by me according to the paper. ~drummyfish }

#include <stdio.h>

#define DIGITS 1000
#define ARRAY_LEN ((10 * DIGITS) / 3)

unsigned int pi[ARRAY_LEN];

void writeDigit(unsigned int digit)
{
  putchar('0' + digit);
}

int main(void)
{
  unsigned int carry, digit = 0, queue = 0;

  for (unsigned int i = 0; i < ARRAY_LEN; ++i)
    pi[i] = 2; // initially pi in this base is just 2s

  for (unsigned int i = 0; i < DIGITS; ++i)
  {
    carry = 0;

    for (int j = ARRAY_LEN - 1; j >= 0; --j)
    { // convert to base 10 and multiply by 10 (shift one to left)

      unsigned int divisor = (j + 1) * 2 - 1; // mixed radix denom.

      pi[j] = 10 * pi[j] + (j + 1) * carry;
      carry = pi[j] / divisor;
      pi[j] %= divisor;
    }

    pi[0] = carry % 10;
    carry /= 10;

    switch (carry)
    { // latter digits may influence earlier digits, hence these buffers
      case 9: // remember consecutive 9s
        queue++;
        break;

      case 10: // ..X 99999.. becomes ..X+1 00000...
        writeDigit(digit + 1);

        for (unsigned int k = 1; k <= queue; ++k)
          writeDigit(0);

        queue = 0;
        digit = 0;
        break;

      default: // normal digit, just print
        if (i != 0) // skip the first 0
          writeDigit(digit);

        if (i == 1) // write the decimal point after 1st digit
          putchar('.');

        digit = carry;

        for (unsigned int k = 1; k <= queue; ++k)
          writeDigit(9);

        queue = 0;
        break;
    }
  }

  writeDigit(digit); // write the last one

  return 0;
}