Pochodzi z http://programmers.blogoverflow.com/2012/08/20-controversial-programming-opinions/
„Biorąc pod uwagę, że Pi można oszacować za pomocą funkcji 4 * (1 - 1/3 + 1/5 - 1/7 +…) z większą liczbą terminów dających większą dokładność, napisz funkcję, która oblicza Pi z dokładnością do 5 miejsc po przecinku. „
- Uwaga: oszacowania należy dokonać poprzez obliczenie sekwencji podanej powyżej.
p=lambda:3.14159
Odpowiedzi:
JavaScript,
46 58 5645 bajtówAktualizacja ES6 : Okazuje się, że po upływie pięciu lat dostępnych jest więcej funkcji.
Ta wersja ( 45 bajtów; tak,
let
jest wymagana) działa teoretycznie w trybie ścisłym ES6 . W praktyce można go uruchomić w wersji V8 (np. Z węzłem) za pomocą--use-strict --harmony-tailcalls
; niestety, funkcja Właściwe ogony nie jest jeszcze powszechnie wdrażana. Jest to jednak określone zachowanie, więc powinno być w porządku.Jeśli chcemy trzymać się tego, co jest powszechnie implementowane, i nie wymagamy trybu ścisłego, możemy po prostu użyć składni Fat-Arrow ES6 dla funkcji, ale w przeciwnym razie zachować tę samą implementację co wcześniej (sugerowana przez Briana H) za koszt 48 bajtów.
Wybór nazwy dla pojedynczego parametru nie naprawdę znaczenia, ale równie dobrze możemy wybrać jedną z nazw, których używamy, aby zminimalizować zanieczyszczenie o zasięgu globalnym.
Ta wersja jest wyrażeniem funkcyjnym; dodaj dwa znaki (np. „
f
”), jeśli chcesz go nazwać. Ta wersja blokuje globalsa
ii
; można temu zapobiec, dodając „a,i
” do listy parametrów.Wykorzystuje przeformułowaną wersję algorytmu w celu obejścia potrzeby odejmowania.
Oto „zwykła” wersja bez tego dostosowania:
która osiąga
6462 znaków.Dzięki @ardnew za sugestię, aby pozbyć się
4*
przedreturn
.Historia
źródło
a+=2/i/-~-~i;return 4*a
naa+=8/i/-~-~i;return a
Python 59 bajtów
Spowoduje to wydrukowanie 1000 cyfr; nieco więcej niż wymagane 5. Zamiast korzystać z przepisanej iteracji, wykorzystuje to:
6637
(Mianownik najgłębsza) można formułować jako:To implikuje liniową zbieżność. Każda głębsza iteracja spowoduje wygenerowanie jeszcze jednego binarnego bitu pi .
Jeśli jednak nalegasz na użycietożsamości tan -1 , możesz osiągnąć podobną zbieżność, jeśli nie masz nic przeciwko temu, aby poradzić sobie z problemem nieco inaczej. Patrząc na kwoty częściowe:
4.0, 2.66667, 3.46667, 2.89524, 3.33968, 2.97605, 3.28374, ...
oczywiste jest, że każdy termin przeskakuje w obie strony w obie strony punktu konwergencji; seria ma przemienną konwergencję. Ponadto, każdy termin jest bliżej punktu zbieżności niż poprzedni termin; jest absolutnie monotoniczny w odniesieniu do punktu zbieżności. Połączenie tych dwóch właściwości implikuje, że średnia arytmetyczna dowolnych dwóch sąsiednich członów jest bliższa punktu zbieżności niż którykolwiek z nich. Aby lepiej zrozumieć, co mam na myśli, rozważ następujący obraz:
Szereg zewnętrzny jest oryginałem, a szereg wewnętrzny można znaleźć, biorąc średnią każdego z sąsiednich terminów. Niezwykła różnica. Ale naprawdę niezwykłe jest to, że ta nowa seria ma również przemienną zbieżność i jest absolutnie monotonna w stosunku do punktu zbieżności. Oznacza to, że proces ten można stosować w kółko, ad nauseum.
Dobrze. Ale jak?
Niektóre formalne definicje. Niech P 1 (n), jest brak p określenie pierwszej kolejności, p 2 (n), jest brak p termin drugiej kolejności, i podobnie P k (n) n p termin z k th sekwencji, jak zdefiniowano powyżej, .
P 1 = [P 1 (1), P 1 (2), P 1 (3), P 1 (4), P 1 (5), ...]
P 2 = [(P 1 (1) + P 1 (2)) / 2, (P 1 (2) + P 1 (3)) / 2, (P 1 (3) + P 1 (4)) / 2, (P 1 (4) + P 1 (5)) / 2, ...]
P 3 = [(P 1 (1) + 2P 1 (2) + P 1 (3)) / 4, (P 1 (2) + 2P 1 (3) + P 1 (4)) / 4, (P 1 (3) + 2P 1 (4) + P 1 (5)) / 4, ...]
P 4 = [(P 1 (1) + 3P 1 (2) + 3P 1 (3) + P 1 (4)) / 8, (P 1 (2) + 3P 1 (3) + 3P 1 (4) + P 1 (5)) / 8, ...]
Nic dziwnego, że współczynniki te są dokładnie zgodne ze współczynnikami dwumianowymi i mogą być wyrażone jako pojedynczy rząd trójkąta Pascala. Ponieważ arbitralny rząd Trójkąta Pascala jest prosty do obliczenia, można znaleźć dowolną „głęboką” serię, po prostu biorąc pierwsze n częściowych sum, mnożąc każdy przez odpowiedni wyraz w k- tym rzędzie Trójkąta Pascala i dzieląc przez 2 k-1 .
W ten sposób można osiągnąć pełną 32-bitową precyzję zmiennoprzecinkową (~ 14 miejsc po przecinku) za pomocą zaledwie 36 iteracji, w których to miejscu częściowe sumy nawet nie są zbieżne na drugim miejscu po przecinku. To oczywiście nie jest gra w golfa:
Jeśli chcesz dowolną precyzję, możesz to osiągnąć z niewielką modyfikacją. Tutaj jeszcze raz obliczając 1000 cyfr:
Początkowa wartość p zaczyna się o 2 10 większa, aby przeciwdziałać efektom s / d dzielenia liczb całkowitych, gdy d staje się większy, powodując, że kilka ostatnich cyfr się nie zbiega. Zauważ tutaj jeszcze raz
3318
jest to również:Ta sama liczba iteracji co pierwszy algorytm (o połowę, ponieważ t zmniejsza się o 1 zamiast 2 w każdej iteracji). Ponownie oznacza to liniową zbieżność: jeden binarny bit pi na iterację. W obu przypadkach wymagane jest 3318 iteracji, aby obliczyć 1000 cyfr liczby pi , ponieważ jest to nieco lepszy przydział niż 1 milion iteracji w celu obliczenia 5.
źródło
4 * sum(1/(1+i*2) if not i%2 else -1/(1+i*2) for i in xrange(places*10**(places)))
k → ∞
,f(-1,k)
zbliża się do twojej sumy Eulera.P_1 = ..., P_2 = ..., P_3 = ..., P_4 = ...
„... pomnożyć każdy przez odpowiedni termin wkth
rzędzie Trójkąta Pascala i podzielić przez2^{k-1}
.”, Zamiastnth
rzędu i2^{n-1}
?Mathematica
42 39 34 33 31 2632Podejście Archimedesa 26 znaków
Osiąga to kryterium, gdy dane wejściowe wynoszą 822.
Pytanie: Czy ktoś wie, jak obliczył grzech 180 stopni? Ja nie.
Podejście Leibniza (seria Gregory'ego) 32 znaki
Jest to ta sama funkcja, którą poser podał jako przykład. Kryterium osiąga około pół miliona iteracji.
Podejście Madhava-Leibniza 37 znaków
Ta odmiana wykorzystuje kilka dodatkowych znaków, ale zbiega się z kryterium tylko w 9 iteracjach!
źródło
APL (14)
źródło
--/4÷1-2×⍳1e6
Java (67 znaków)
Zauważ, że pozwala to uniknąć utraty znaczenia poprzez dodanie liczb w odpowiedniej kolejności.
źródło
while(--i>0)
, abywhile(i--)
i zaoszczędzić 2 znakiHaskell, 32
Liczenie nazwy funkcji to
34
źródło
R - 25 znaków
źródło
C (GCC) (44 znaki)
To 41 znaków, ale należy je również skompilować,
-O2
aby uzyskać optymalizator eliminujący rekurencję ogona. Zależy to również od nieokreślonego zachowania w odniesieniu do kolejności, w jakiej++
są wykonywane; dzięki ugoren za zwrócenie na to uwagi. Testowałem z gcc 4.4.3 pod 64-bitowym Linuksem.Pamiętaj, że jeśli optymalizator nie zmieni również kolejności sumy, zostanie ona dodana od najmniejszej liczby, aby uniknąć utraty znaczenia.
Jak zadzwonić
p()
.źródło
q()
nie jestp()
. I nie sądzę, że-O2
należy to liczyć (ale jeśli to policzysz, to 4 znaki z powodu wymaganej przestrzeni).p(0)
. 3. Zapisz znak przezreturn++i...
. 4. Dwa++i
powodują niezdefiniowane zachowanie.q
- nauczy mnie to podwójnego sprawdzania po zmianie nazwy. Myślę, że przestrzegam normalnej praktyki liczenia-O2
jako 3 znaki, ale możemy otworzyć ją na meta, jeśli chcesz; meta.codegolf.stackexchange.com/questions/19 to jedyna istotna dyskusja, jaką mogę znaleźć. Dodałem wersję gcc, której używam i która pozwala mi nazywać ją jakop()
. Zapisanie znaku zatrzyma optymalizator i spowoduje awarię. Wyjaśnięp()
- czy na pewno zadzwonip()
z dowolnego kontekstu? A może tak właśnie było na stosie w teście?p()
vsp(0)
, ale nie wiem, jakie zachowanie dokumentuje, i tak naprawdę nie jestem programistą C.J, 26 znaków
+ / + / _ 2 ((4 _4) i%)>: +: i.100Przeniesiono ze 100 elementów sekwencji do 1e6 elementów. Również teraz jest to kod oznaczony i może być kopiowany z przeglądarki do konsoli bez błędów.
źródło
-/4%>:2*i.1e6
- 13 znaków. (Dzięki b_jonas w #jsoftware za uświadomienie mi, że-/
działa, aby obliczyć sumę ze znakiem naprzemiennym. [Dzieje się tak, ponieważ wszystkie operatory w J mają równy priorytet i są odpowiednio asocjatywne, więc-/ 1 2 3 4
<=>1 - (2 - (3 - 4))
<=>1 - 2 + 3 - 4
.])JavaScript - 33 znaków
Zadzwoń
p
podając dodatnią liczbę nieparzystą,x
a wyliczy Pi z(x-1)/2
warunkami.źródło
Rubin - 82 znaki
Wypróbuj: https://repl.it/LQ8w
W podejściu wykorzystuje się daną serię pośrednio, stosując metodę przyspieszenia numerycznego. Wynikowy wynik to
pi ≈ 3.14159265161
vs.
pi = 3.14159265359
Zaczyna się od
A ponieważ jest to na przemian, możemy przyspieszyć konwergencję za pomocą
I wielokrotnie stosuje to:
I dla uproszczenia
f(n) = f(n,n)
.Rubin - 50 znaków
Jeśli nie masz nic przeciwko bieganiu przez naprawdę długi czas, możesz po prostu użyć
lub
źródło
C, 69 znaków
a
jest inicjowany na 1).void main
jest dziwny i niestandardowy, ale sprawia, że wszystko działa. Bez tego rekurencja jest implementowana jako prawdziwe wywołanie, co prowadzi do przepełnienia stosu. Alternatywą jest dodawaniereturn
.4*
Można zapisać dwa znaki , jeśli działają z trzema parametrami wiersza poleceń.źródło
int main(a)
a nawetmain(a)
GCC daje tylko ostrzeżenie. I tak da ostrzeżenievoid main
, a może nawet dlatego, że masz tylko jeden argumentmain
.Clojure - 79 znaków
Tworzy to funkcję bez argumentów, która obliczy liczbę zmiennoprzecinkową, która poprawnie przybliża pi do pięciu miejsc po przecinku. Należy zauważyć, że to nie wiąże funkcja nazwę, na przykład
pi
, tak, że kod musi być albo oceniona na miejscueval
, jak(<code>)
i związany z nazwy w tym przypadku roztwór jestdla 82 znaków
O
źródło
PHP -
5655 znakówNie wiem, czy mogę go znacznie zmniejszyć, nie naruszając reguły algorytmu.
źródło
<?for(;1e6>$j;)$p+=($i=-$i|4)/~-$j+=2;echo$p;
Perl -
4339 znakównie jestem pewien zasad dotyczących anonimowych podprogramów, ale oto kolejna implementacja wykorzystująca konstrukcję serii @ FireFly
źródło
Java -
9284 znakówZdecydowanie nie mogę pokonać wyniku Petera Taylora, ale oto mój:
Wersja bez golfa:
Edycja: Zapisano kilka znaków przy użyciu operatora trójskładnikowego.
źródło
Python - 56 znaków
Meh, Moje python-fu nie jest wystarczająco silne. Nie widziałem żadnych skrótów, ale może bardziej doświadczony golfista mógłby znaleźć coś do przycięcia?
źródło
4.
->4
). W innych wiadomościach właśnie znalazłem przypadek, w którym Python 3 faktycznie pokonuje Python 2 w golfowym kodzie!Rubin - 54 znaki
Moja pierwsza próba na konsoli
63 znaki.
źródło
def a;
zamiastdef a()
.Perl (76 chars)
(Result: 3.14159052)
Not the shortest possible solution, but maybe interesting. It's a geometrical one. I calculate the area under a circle.
I got another funny approach, but it's really slow. It counts the number of discrete points in a square that are below a quarter circle and calculates pi from it:
It expects the number of iterations as command line argument. Here you can see how run time relates to accuracy. ;)
źródło
k (25 chars)
4*+/%(i#1 -1)'1+2!i:1000000Slightly shorter:
źródło
Python (49)
źródło
CJam - 21
Pretty straightforward calculation of the given series.
CJam is http://sf.net/p/cjam
źródło
Julia - 30 characters
źródło
SQL, 253 bytes
I would provide a SQL Fiddle, but this goes too many loops deep finding the 1/3 1/5 1/7 etc. fractions and gives errors lol. However, if you change
@B<100000
to1000
then it runs (obviously not to the same number of digits of accuracy).źródło
Befunge, 129 bytes
Try it online!
In case anyone is wondering, it's an elephant.
źródło