Liczba „e”: Z dokładnością do miliona miejsc po przecinku

Obliczanie liczby e z szeregu Taylora w języku C, z użyciem GMP do uzyskania miliona cyfr po przecinku.

Liczba „e”: Z dokładnością do miliona miejsc po przecinku

Szereg Taylora funkcji $e^x$

Liczba $e$ ma wiele ciekawych własności i zastosowań, a dodatkowo ciekawe jest też to, że szereg Taylora będący rozwinięciem funkcji $e^x$ dla $x=1$ jest dodatni (nie naprzemienny) i bardzo szybko zbieżny. Jest tak dlatego, że ma silnię kolejnych indeksów sumy w mianowniku:

\[e^x=\sum_{n=0}^{\infty}\frac{x^n}{n!} \:\:\Rightarrow\:\: e=\sum_{n=0}^{\infty}\frac{1}{n!}.\]

Skoro tak, to łatwo jest napisać kod np. w C, który liczy ten szereg z dobrą precyzją, a z użyciem biblioteki GMP z dowolną precyzją.

GMP (GNU Multiple Precision Arithmetic Library) to biblioteka do obliczeń na liczbach o dowolnie dużej precyzji, znacznie większej niż oferowana przez standardowe typy zmiennoprzecinkowe, ograniczonej jedynie dostępną pamięcią.

Obliczanie liczby $e$ z szeregu Taylora

Tutaj zamieściłem dwa kody:

  • zwykłe C, bez GMP, oblicza $e$ do dziesięciu miejsc po przecinku: e_number.c
  • analogiczny kod z GMP, oblicza $e$ do miliona miejsc po przecinku: e_number_gmp.c

Wynikiem kodu e_number.c jest liczba $e=2.7182818284$..

Wynikiem kodu e_number_gmp.c jest liczba $e$ z milionem miejsc po przecinku, zapisana w pliku e_number_gmp.txt. Pierwsze 1000 z miliona cyfr po przecinku wygląda tak:

e = 2.718281828459045235360287471352662497757247093699959574966967627724076630353545
713821785251664274274663919320030599218174135966290435729003342952605956307381323286
279434907632338298807531952510190115738341879307021540891499348841675092447614606680
822648001684774118537423454424371075390777449920695517027618386062613313845830007520
449338265602976067371132007093287091274437470472306969772093101416928368190255151086
574637721112523897844250569536967707854499699679468644549059879316368892300987931277
361782154249992295763514822082698951936680331825288693984964651058209392398294887933
203625094431173012381970684161403970198376793206832823764648042953118023287825098194
558153017567173613320698112509961818815930416903515988885193458072738667385894228792
284998920868058257492796104841984443634632449684875602336248270419786232090021609902
353043699418491463140934317381436405462531520961836908887070167683964243781405927145
6354906130310720851038375051011574770417189861068739696552126715468895703503540212..

Jest więcej takich obliczeń, np. w projekcie y-cruncher na numberworld.org, wraz z dużymi rekordami wyników dla $e$, $\pi$ i innych stałych.

Zrobiłem też kiedyś skład w LaTeX-u ciekawej książki na ten temat i napisałem do niej przedmowę: Number e to Approximately 1 Million Places.

Kod w C (bez GMP)

Prosty kod w C bez GMP, który sam się tłumaczy, z pliku e_number.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
/*
 Obliczenie liczby e bez GMP (mała precyzja).
 Liczymy szereg: e = sum_{n=0..∞} 1/n!
 Zatrzymanie po osiągnięciu zadanego progu eps,
 a wynik wypisywany do 10 miejsc po przecinku.

 Kompilacja: gcc e_number.c -O2 -o e_number.exe
 */

int main(void)
{
    const int DIGITS = 10;
    const long double eps = 1e-12L;  // zapas w stosunku do 1e-10

    long double e = 1.0L;      // suma
    long double term = 1.0L;   // 1/0!
    unsigned long k = 1;

    // zatrzymanie, gdy kolejny wyraz jest na tyle mały, że nie wpływa na wynik
    while (term > eps) {
        term /= (long double)k;   // term = 1/k!
        e += term;
        k++;
    }

    printf("e = %.*Lf\n", DIGITS, e);
    printf("Uzyte wyrazy szeregu: %lu\n", k);

    return 0;
}

Kody C kompiluję w MinGW:

1
2
gcc e_number.c -O2 -o e_number.exe
gcc e_number_gmp.c -O2 -lgmp -o e_number_gmp.exe

Robię → działa → jest fajnie.

To zamyka serię trzech wpisów o liczbie $e$: od intuicji, przez wzór Eulera i szereg Taylora, do obliczeń z precyzją miliona cyfr po przecinku.

© Marcin Szewczyk. Wszelkie prawa zastrzeżone.