Jak wydrukować pi (3.14159)? [Zamknięte]


35

Jakie polecenie może dla mnie wypisać pi? Chcę określić, ile cyfr ma drukować, nie mogłem znaleźć niczego online. Chcę tylko móc wydrukować pi.



4
Zwróć uwagę, że jest przyjemniej, jeśli chcesz mieć więcej cyfr niż około 15.
Thorbjørn Ravn Andersen

2
@DisplayName: oznacza to, że nie można już używać żadnego programu, który wewnętrznie przechowuje / oblicza PI przy użyciu wartości zmiennoprzecinkowych o podwójnej precyzji (zwykle jest to wbudowany typ danych FP o największej precyzji dostępny w większości języków).
Matteo Italia,

5
Moje rozwiązanie sprzed dziesięcioleci, zanim zostało to powszechnie zapewnione przez biblioteki językowe, polegało na zapamiętywaniu go w większej liczbie miejsc, niż te, których używałem zmiennoprzecinkowe, których kiedykolwiek potrzebowałem: 3.1415926535897932384626 jest zwykle wystarczająco blisko do celów praktycznych, a nawet najbardziej niepraktycznych - cokolwiek realnego -world będzie miał więcej błędów niż w innych liczbach, a dla teorii trzymałbym się raczej wartości symbolicznych niż liczbowych.
keshlam

3
Zainteresowanie @syntaxerror nie ma znaczenia. Jeśli opublikujesz pytanie z nagimi zdjęciami celebrytów, uzyskasz tysiące wyświetleń i być może pozytywnych opinii. To nie dotyczy tematu. To pytanie jest klasycznym przykładem zbyt szerokiego. Wystarczy spojrzeć na liczbę odpowiedzi. Należy również zauważyć, że PO nie określił żadnych ograniczeń, które czynią możliwe odpowiedzi w zasadzie nieskończonymi. W każdym razie zamknięcie nie jest kasowane. Pytanie i wszystkie 23 odpowiedzi nadal będą dostępne. Zamknięcie oznacza po prostu, że nie są już akceptowane żadne odpowiedzi. Czy naprawdę potrzebujemy jeszcze więcej sposobów drukowania π?
terdon

Odpowiedzi:


52

Możesz użyć tego polecenia:

echo "scale=5; 4*a(1)" | bc -l
3.14159

Gdzie skala to liczba cyfr po przecinku.

Odniesienie: http://www.tux-planet.fr/calculer-le-chiffre-pi-en-ligne-de-commande-sous-linux/


12
Krótsza wersja bashi inne pociski wspierające tutaj ciągi: bc -l <<< "scale=5; 4*a(1)".
pabouk

2
Zastanawiam się, ile cyfr to może iść?
DisplayName

4
@DisplayName całkiem sporo. scale=1000daje 999 poprawnych cyfr raczej szybko (ostatnia cyfra jest wyłączona o 1, rozsądne, ponieważ obliczamy pi / 4, a następnie mnożymy przez 4). scale=4000daje 4000 poprawnych cyfr w kilka sekund. scale=10000trwa dłużej niż mam cierpliwość, ale prawdopodobnie daje 9999 lub 10000 poprawnych cyfr.
hobbs

4
Daje to niepoprawny wynik na moim komputerze, wpisując skalę „echo” = 5; 4 * a (1) „| bc -l 'zwraca 3,14156, kiedy ostatnia cyfra powinna być o 9
Jordan Bentley


61

Jeśli tex(1)zainstalowałeś:

tex --version | head -1 | cut -f2 -d' '

13
Jest to prawie warte pochwały za to, że jest sprytny. Chociaż wynik tego zmienia się po uaktualnieniu pakietu. Czy uznamy to za cechę lub błąd?
CVn

8
@ MichaelKjörling W rzeczywistości zmienia się na bardziej precyzyjne przybliżenie pi.
Abrixas2,

@ Abrixas2 Tak, wiem. Ostatnia wersja TeXa to wersja π.
CVn

30
@DavidRicherby Mniej cyfr można wydrukować poprzez dodatkowe wywołanie cut. Więcej cyfr można wydrukować, czekając długo i ponownie uruchamiając polecenie.
Steven D,

1
@ Ruslan zależy od implementacji. Oczekiwałbym w tym konkretnym przypadku, że byłoby to zrobione „dobrze”.
Thorbjørn Ravn Andersen

23

Do drukowania z dowolną precyzją można użyć bcformuły pi = 4*atan(1):

# bc -l
scale=<your precision>
4*a(1)

2
Jest coś zabawnego w tej scaleopcji, pi = 3.141592..ale z echo "scale=5; 4*a(1)" | bc -l => 3.14156tym spodziewałbym się zobaczyć 3.14159?
fduff

7
scaleokreśla precyzję używaną do obliczeń, więc przy scale=5żadnej operacji żadna operacja atomowa nie użyje więcej niż pięciu cyfr ułamkowych.
Abrixas2


20

Jeśli chcesz czegoś, co może obliczyć wartość π, istnieje kilka podejść. Być może najbardziej oczywistym rozwiązaniem byłoby użycie gotowego pakietu, takiego jak pi(link do pakietu Debiana) , który jeśli można zaufać opisowi pakietu Debian, może obliczyć wartość z dowolną dokładnością, ograniczoną tylko pamięcią.

pijest właściwie przykładem zawartym w bibliotece CLN (Class Library for Numbers) . Zawiera przykładowe aplikacje, które zapewniają narzędzia do generowania dowolnych długości liczb, takich jak Pi, Fibonacci itp. Pakiety CLN są dostępne w paczkach w Debianie / Ubuntu (na to wskazuje powyższy link Debiana).

Przykłady
$ ./pi 10
3.141592653

$ ./pi 20
3.1415926535897932384

UWAGA: Źródło tych przykładów znajduje się tutaj w źródle podstawy kodu CLN .

Inne dystrybucje

Fedora

Na Fedorze musiałem pobrać źródłowy plik archiwum i sam go zbudować, ale kompiluje się bez większego zamieszania. Z jakiegokolwiek powodu pakiet clnna Fedorze zawiera tylko bibliotekę, ale pomija przykłady dostępne w wersji Debian / Ubuntu (powyżej).

Łuk

Arch zapewnia ten sam program w tym clnopakowaniu (dzięki Amphiteót ).


Tak, heh miałem na myśli całkowitą wartość, którą właśnie wpisałem, co miałem w głowie.
DisplayName,

2
„Całkowita wartość”? Znaczy co...?
Kyle Strand

2
@DisplayName przeczytaj resztę odpowiedzi. Dedykowany program jak pibrzmi dokładnie tak, jak szukasz. Możesz na przykład pi 300wydrukować pierwsze 300 cyfr.
terdon

3
@KyleStrand Odkryłem naprawdę cudowną odpowiedź na to pytanie, które ten komentarz jest zbyt wąski, aby go zawrzeć. Hej, to zadziałało dla Fermata !
terdon

Chciałbym wiedzieć, dlaczego otrzymano dwa głosy negatywne. Czy osoby, które przegłosowały głosowanie, nie przeczytały odpowiedzi, zanim zdecydowały, że nie jest to przydatne?
CVn

17

Dla maksymalnie miliona cyfr możesz użyć następujących (tutaj dla 3000 cyfr):

curl --silent http://www.angio.net/pi/digits/pi1000000.txt | cut -c1-3000

2
Ma to dodatkową zaletę, że powinno być rozsądnie zbliżone do złożoności O (1). A może to wcale nie jest korzyść ...
CVn

7
Trudno też powiedzieć, że jakakolwiek interakcja sieciowa jest złożonością czasową O (1) w praktycznym świecie. : P
HalosGhost

2
@HalosGhost Dla naszych celów (w porównaniu do obliczania n cyfr liczby pi za każdym razem), pobieranie stałej ilości danych z określonego serwera przez sieć prawdopodobnie będzie efektywnie O (1), podczas gdy obliczenie n cyfr liczby pi przynajmniej coś takiego jak O (log n) i całkiem możliwe, że wyższy (nie znam tych algorytmów). Rzeczywiste pobieranie danych może zająć znacznie więcej czasu niż narzut, aby rozpocząć pobieranie, dlatego czas pobierania dominuje i dostajesz się gdzieś w pobliżu O (1), biorąc pod uwagę dość stałą szybkość transmisji danych. Stąd O (1).
CVn

4
@ MichaelKjörling Kiedy mówisz O (1), tak naprawdę nie masz na myśli O (n)? Czas pobierania liniowo w liczbie potrzebnych cyfr, stąd O (n).
CodesInChaos

1
@CodesInChaos Nie, czas pobierania jest stały (biorąc pod uwagę stałą szybkość transmisji), ponieważ pobierasz stałą liczbę cyfr (tutaj jeden milion). Chyba że (w tym konkretnym przypadku) zwijanie jest wystarczająco inteligentne, aby drukować podczas pobierania i zatrzymać pobieranie po zerwaniu rury, ponieważ cutkończy się? Jeśli tak jest, zgadzam się, że byłoby O (n).
CVn

15

Niektóre inne odpowiedzi pokazują niepoprawne cyfry w ostatnich miejscach wyjścia. Poniżej znajduje się odmiana odpowiedzi przy użyciu,bc ale z poprawnie zaokrąglonym wynikiem. Zmienna szawiera liczbę cyfr znaczących (w tym 3przed kropką dziesiętną).

Zaokrąglić do połowy

$ bc -l <<< "s=5; scale=s+2; pi=4*a(1)+5*10^(-s); scale=s-1; pi/1"
3.1416

Zaokrąglaj w dół (obcinaj)

$ bc -l <<< "s=5; scale=s+2; pi=4*a(1); scale=s-1; pi/1"
3.1415

Objaśnienie zaokrąglenia

Zaokrąglanie odbywa się bezpośrednio w bc. Nie ma to ograniczenia polecenia, printfktóre używa reprezentacji doubletypu języka C dla liczb, które mają dokładność około 17 cyfr znaczących. Zobacz odpowiedź printfzaokrąglając .

scale=s-1ustawia liczbę cyfr, które mają zostać obcięte. pi/1dzieli wynik przez 1, aby zastosować obcinanie. Prosty pinie obcina liczby.

Zaokrąglanie w górę pół wymaga, aby dodać 5 do pierwszej cyfry, które zostaną odcięte (5 x 10 -s ), tak, że w przypadku wyższych cyfr równej 5 ostatnia cyfra, która pozostanie zostanie zwiększony.

Z testów przeprowadzonych przez hobbs wydaje się, że trzy dodatkowe cyfry, które zostaną zaokrąglone / odcięte ( scale=s+2), wystarczą nawet dla bardzo długich liczb.

Tutaj sznurki

Powyższe przykłady zastosowania tutaj ciągi , które są obsługiwane na przykład bash, kshi zsh. Jeśli twoja powłoka nie obsługuje tutaj ciągów znaków echoi potoku zamiast tego:

$ echo "s=5; scale=s+2; pi=4*a(1); scale=s-1; pi/1" |  bc -l
3.1415

2
Obliczenie trzech dodatkowych cyfr w celu zaokrąglenia nie jest „poprawnym zaokrągleniem”, jak twierdzi się w komentarzu. Po pierwsze, nie masz ograniczenia związanego z błędem obliczeń. Jeśli może być źle przez 3 jednostki na ostatnim miejscu, jak twierdzi fduff, dlaczego nie byłoby źle przez 1000 jednostek na ostatnim miejscu? Po drugie, patrz „dylemat twórcy stołu”.
Skomplikowane, patrz bio

12

perl jedna linia (używając bignum ):

perl -Mbignum=bpi -wle 'print bpi(NUM)'

na przykład

perl -Mbignum=bpi -wle 'print bpi(6)'
3.14159

Dla 10.000 cyfr: blisko 8 minut w perlu, mniej niż 4 w bc. Nie najszybszy.
Izaak

9

Z python2:

$ python -c "import math; print(str(math.pi)[:7])"
3.14159

4
Ze względu na kompletność, to rozwiązanie jest specyficzne dla python2.
HalosGhost,

Po edycji (..)działa to w Pythonie 2 i 3. Wydaje się, że ma tylko 12 cyfr.
Anthon

$ Python -c "import matematyki; druku (format (Math.PI '.400f'))" 3,1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Artem Shitov

1
@ArtemShitov - mój źle, spróbuj importowania gmpy2 (jeśli masz go zainstalowanego) python -c "import gmpy2; print(str(gmpy2.const_pi(8192))[:400])". Zwiększ precyzję, aby uzyskać więcej cyfr ... np.python -c "import gmpy2; print(str(gmpy2.const_pi(16384))[:4400])"
don_crissti

1
Najszybszy, jaki udało mi się znaleźć, to from mpmath import mp; mp.dps = 1000000 ; print(mp.pi)zaledwie kilka sekund na milion cyfr. Tak ogólnie to nieźle !!!.
Izaak

7

Za pomocą Ruby:

require "bigdecimal"
require "bigdecimal/math"
include BigMath

BigDecimal(PI(100)).round(9).to_s("F")

3.141592654

1
Jedna linijka:ruby -e 'require "bigdecimal"; require "bigdecimal/math"; include BigMath; puts BigDecimal(PI(100)).round(9).to_s("F")'

4

W bash:

$ read -a a <<< $(grep M_PIl /usr/include/math.h) ; echo ${a[3]} | tr -d L
3.141592653589793238462643383279502884

@ Amphiteóth afmtoditwymaga groffinstalacji. Tutaj na Ubuntu (i smakach), to nie norma. JFYI.
składniaerror

@syntaxerror Dziękuję, dobry punkt! Usunąłem mój przykład. Chodzi mi o to, kiedy przeczytałem, że AI uruchomiło się grepw moim systemie, szukając stałej i znalazłem ją w więcej niż jednym miejscu. To dla mnie było +1!


3

Jak przegapiłem to pytanie ...

Oto mój mały program Python pi, który zamieściłem kilka tygodni temu na Stack Overflow. Nie jest to szczególnie szybkie, ale potrafi zrobić wiele cyfr. :) Jednak, jak wspomniałem w tym wątku, zwykle używam modułu mpmath Pythona do arytmetyki o dowolnej precyzji, a mpmath ma dość szybki program do tworzenia pi.

Na przykład,

time python -c "from mpmath import mp;mp.dps=500000;print mp.pi" >bigpi

real    0m4.709s
user    0m4.556s
sys     0m0.084s

500 000 miejsc po przecinku w mniej niż 5 sekund nie jest zbyt odrapane, IMHO, biorąc pod uwagę, że działa na maszynie z pojedynczym rdzeniem 2GHz, 2 gig RAM i zapisuje na starszym dysku IDE.


Spróbuj from mpmath import mp; mp.dps = 1000000 ; print(mp.pi)(po instalacji mpmath pip3) w ciągu dwóch sekund na milion cyfr. Tak ogólnie to nieźle !!!.
Izaak

2

Jeśli node.jszainstalowałeś, zrobi to najlepiej, aby znaleźć pi dla ciebie, chociaż jego najlepsze nie jest zbyt dobre:

node -e 'for(a=0,b=4E8,m=Math,r=m.random;b--;)a+=(1>m.sqrt((c=r())*c+(d=r())*d));console.log(a/1E8)'

Przykładowe wyniki:

3.14157749
3.1416426
3.14159055
3.14171554
3.14176165
3.14157587
3.14161137
3.14167685
3.14172371

4
Krótszy node -e 'console.log(Math.PI)'jest trochę lepszy niż najlepszy.
chbrown

1
@chbrown To nie spełnia wymagań „niepoważnych” PO.
Paul,

1
Jakie „niepoważne” wymaganie? PO właśnie stwierdził, że prosi o zabawę, a nie to, że chcą odpowiedzi, które są w jakiś sposób „niepoważne”. Co to w ogóle znaczy? Coś takiego echo pie?
terdon

Napisałem to, ponieważ kiedy zadajesz pytania, czasami ludzie mówią, że „to nie jest fabryka pisania skryptów”, więc powiedziałem, że ponieważ nie ma prawdziwego powodu, chcę tylko wiedzieć, jak wydrukować pi.
DisplayName

@ Amphiteóth Uruchomienie na moim komputerze zajmuje około 20 sekund. Być może będziesz musiał poświęcić trochę czasu.
Paul

2

Metoda Monte Carlo

Patrz, na przykład ten o wyjaśnienie tej metody.

Ostrzeżenia

  • Nie arbitralnie dokładne
  • Długo trwa konwergencja na coś użytecznego

Zalety

Zabawa :-)

perl -Mbignum -E '
    for(0 .. 1_000_000){
        srand;
        $x=rand; # Random x coordinate
        $y=rand; # Random Y coordinate
        $decision = $x**2 + $y**2 <=1 ? 1:0; # Is this point inside the unit circle?
        $circle += $decision;
        $not_circle += 1-$decision;
        $pi = 4*($circle/($circle+$not_circle)); 
        say $pi
     }'

Uwaga: najpierw spróbowałem bez, srandale utknął, 3.14a cyfry dalej oscylowały, nigdy się nie zbiegając. Jest tak prawdopodobnie dlatego, że po chwili PRNG zaczyna się powtarzać. Zastosowanie srandspowoduje uniknięcie tego lub przynajmniej wydłuży okres pseudolosowej sekwencji. To wszystko przypuszczenie, więc nie wahaj się mnie poprawić, jeśli się mylę.


@ Amphiteót Nie bardzo wiem, co się tam dzieje. Jeśli to pomaga mojemu Perlowi jest v5.14.2. Obawiam się, że nie znam się na bignumoperacjach w Perlu i nie znam żadnych konkretnych części powyższego programu, które wymagałyby nowszego Perla. W każdym razie interesujący jest sam algorytm. Spróbuj wdrożyć go w wybranym języku, jeśli ten Perl nie działa dla Ciebie.
Joseph R.

1
@ Amphiteót Rozumiem. Czy edycja rozwiązuje Twój problem?
Joseph R.

@ Amphiteót Możesz spróbować dodać ($x,$y,$circle,$not_circle)=(0,0,0);przed pętlą, aby upewnić się, że wszystkie zmienne są zdefiniowane przed użyciem.
Joseph R.

@ Amphiteót Mój błąd. Powyższe pareny powinny były być (0,0,0,0).
Joseph R.

Re tym /5.20.1: To ma sens, ale nie to zobaczyć! Rzeczywiście ($x,$y,$circle,$not_circle)=(0,0,0,0). Po minucie lub dwóch krążyło wokół pożądanej wartości, a potem zatrzymałem się znacznie bliżej 3,1409. Ciekawe i zabawne! Dziękuję Ci!

2

Możesz użyć algorytmu czopka dla pi. Poniższy program C autorstwa Dika Wintera i Achima Flammenkampa da pierwsze 15 000 cyfr liczby pi, po jednej cyfrze na raz.

a[52514],b,c=52514,d,e,f=1e4,g,h;main(){for(;b=c-=14;h=printf("%04d",e+d/f))for(e=d%=f;g=--b*2;d/=g)d=d*b+f*(h?a[b]:f/5),a[b]=d%--g;}

Kontekst: wiki , tu i tutaj .

1
Uwielbiam algorytm czopkowy dla stałych logarytmicznych Borweina, Baileya i Plouffe, jednak nie jest to golf golfowy, więc czy mogę poprawić czytelność kodu poprzez jego ponowne sformatowanie? Zauważ też, że algorytmy w stylu BPP mogą wyprowadzać cyfry pi tylko w bazach o sile 2, przynajmniej bez użycia dodatkowej pamięci.
Franki,

@Franki czy formatowanie kodu zmienia znaczenie lub intencję postu? Jeśli nie, wszystko powinno być w porządku (i zawsze można cofnąć edycję). Nie rozumiem, jak odszyfrowanie jakiegoś kodu może zrobić coś innego niż wyjaśnienie.
11684

1
@syntaxerror Należy zatrzymać dokładnie 15 000 cyfr. Dane wyjściowe w drugiej pętli for dają 4 cyfry liczby pi i zmniejszają tajemniczą liczbę 52514 o 14. Równanie byłoby wówczas 4 * (52514/14), co równa się 15004. Ostatnie 14 wartości w tablicy są ignorowane, aby wziąć korzyść z mniejszej liczby żetonów, aby uzyskać naszą dokładną wartość 15000.
Daniel Henneberger

1
@ 11684 Nie, to naprawdę nie zmieni znaczenia ani intencji kodu. Jednak zdałem sobie sprawę, że nie jest to algorytm czopowy typu BBP dla pi, ale inny, który ktoś już tutaj zdefektusował tutaj stackoverflow.com/a/25837097
Franki,

2

PHP

Kilka przykładów:

php -r "print pi();"
php -r 'echo M_PI;'
echo "<?=pi();" | php

Jeśli chcesz zmienić precyzję, spróbuj:

php -d precision=100 -r 'echo pi();'

Rozmiar liczby zmiennoprzecinkowej jest zależny od platformy, chociaż wspólna wartość to maksymalnie ~ 1,8e308 z dokładnością około 14 cyfr dziesiętnych (64-bitowy format IEEE). [Czytaj więcej]


Jeśli szukasz jeszcze dokładniejszej precyzji, sprawdź Rosetta Code lub Code Golf SE, aby znaleźć rozwiązania programistyczne.

Powiązane: Oprogramowanie, które może obliczyć PI do co najmniej tysiąca cyfr w SR.SE


1

Oto skrypt, który wypisuje pi z liczbą cyfr określoną (łącznie z „.”) Przez użytkownika.

pi.sh

#!/bin/bash
len=${1:-7}
echo "4*a(1)" | bc -l | cut -c 1-"$len"

wydajność

$ ./pi.sh 10
3.14159265

i z wartością domyślną:

$ ./pi.sh
3.14159

Widziałem ludzi korzystających scalez bcopcji, ale w moim przypadku ( bc 1.06.95) nie wyświetla to poprawnej wartości:

$ echo "scale=5;4*a(1)" | bc -l
3.14156

Zwróć uwagę na ostatnią cyfrę.


4
Pytanie brzmi: „Chcę określić, ile cyfr drukuje”, co, ściśle mówiąc, jest dwuznaczne - ale myślę, że twoja odpowiedź zawodzi (z technicznego punktu widzenia) przy jakiejkolwiek rozsądnej interpretacji; Twoje ./pi.sh 10odciski dziewięciu cyfr, liczenie początkowe 3. Wskazujesz również błąd zaokrąglania, ale ./pi.sh 6wyniki 3.1415, które mogą nie być optymalne.
G-Man mówi „Przywróć Monikę”

Z pamięci scale=Xopcja bcNIE zaokrągli liczby, ale po prostu odetnie liczbę przy X-tej cyfrze dziesiętnej.
składniaerror

1

Podoba mi się odpowiedź Abeya, ale nie podobało mi się, jak bc zmieniał ostatnią cyfrę.

echo "scale=5; 4*a(1)" | bc -l
3.14156

Więc usunąłem skalę używaną printf, aby ustawić liczbę cyfr.

printf "%0.5f\n" $(echo "4*a(1)" | bc -l)
3.14159

Zauważyłeś, że po skali 62 cyfr wszystkie mają wartość 0, podczas gdy nie dzieje się tak w przypadku oryginalnego polecenia.

2
@ Amphiteót, To dlatego, że printfma poważne ograniczenie liczb zmiennoprzecinkowych w porównaniu do bc. Są one reprezentowane przez doubletyp języka C z dokładnością około 17 cyfr, więc nawet niezerowe cyfry po około 17 cyfrach są fałszywe! ------ Dodałem odpowiedź z poprawnym zaokrągleniem wyniku nieograniczonego przezprintf . ------ Również, aby upewnić się, że to polecenie działa z różnymi ustawieniami narodowymi, musisz zrobić coś takiego: LC_ALL=C printf...
pabouk,

1

Co jeśli nie możesz sobie przypomnieć tego życia arctan? Załóżmy, że nawet nie wiesz, że ta funkcja istnieje bc, a następnie spróbuj zapamiętać ten prosty podział:

echo "scale=6; 355 / 113" | bc
3.141592

Będzie działać tylko dla 6 cyfr, ale w przypadku obliczeń nienaukowych będzie to dobrze.

Jeśli uważasz, że nie pamiętasz tych dwóch liczb, najpierw napisz mianownik, a następnie licznik:

113 355

A dlaczego nie

11 33 55

„podwójne 1, podwójne 3, podwójne 5”. Wszystkie liczby są nieparzyste. Aby obliczyć, ponownie podziel 6-cyfrową liczbę na pół i zamień mianownik i licznik przed ich podzieleniem. O to chodzi.


Jeśli o mnie chodzi, 4 * arctan(1)o wiele łatwiej mi zapamiętać, że 2 trzycyfrowe liczby ... Z łatwością użyłbym 335 zamiast 355 lub 133 zamiast 113.
John WH Smith

Cóż, myślę, że jest to kwestia osobistych preferencji. :) Ludzie (jak ja), którzy mogą łatwo zapamiętać (telefony stacjonarne!) Numery telefonów, mogliby zapamiętać dwa numery jak jeden numer telefonu. Pomoże również tym ludziom, którzy w szkole czuli, że trygonometria musiała być wykonana przez złe moce.
składniaerror

1

Można założyć, że OP jest zainteresowany krótkim, łatwym do zapamiętania poleceniem powłoki, aby wydrukować π - ale pytanie tak naprawdę nie mówi. Ta odpowiedź ignoruje to założenie i odpowiada na pytanie dokładnie tak, jak napisano;

Trywialny?

Chociaż jest już 18 odpowiedzi, wciąż brakuje jednego podejścia - a przy tak wielu odpowiedziach można by pomyśleć, że nie brakuje tylko jednego:
Trywialne: Jak wydrukować π? Po prostu wydrukuj π!

Takie podejście wydaje się zbyt bezużyteczne, aby nawet o tym myśleć, ale pokażę, że ma swoje wady:

Zoptymalizowany

Zwykle obliczamy wartość π. Nie widzę, co powstrzymuje nas przed optymalizacją rozwiązania, przez wstępne obliczenie wartości - jest to stała, zrobiłby to każdy kompilator.

Chcemy pewnej liczby cyfr π, z maksymalną precyzją. Możemy więc wziąć prefiks stałej jako tekst:

echo 3.1415926535897932384626433832795 | cut -b -7
3.14159

Wariant z wyraźnym argumentem za precyzją, np. dla precyzji 5:

echo 3.1415926535897932384626433832795 | cut -b -$((2+5))
3.14159

Zalety

Maksymalną precyzję można wybrać dowolnie, stosując odpowiednią stałą obliczoną przy użyciu jednej z pozostałych odpowiedzi. Jest ograniczony tylko maksymalną długością wiersza poleceń.
Ma stałą złożoność czasową w celu znalezienia wartości.
Sprawia, że ​​wszystkie ograniczenia i ograniczenia są oczywiste, w oparciu o małą złożoność implementacji.
Z wdziękiem obsługuje precyzję większą niż maksimum, zwracając stałą z pełną dostępną precyzją (bez trailing 0).
To trywialne rozwiązanie ma jednak zalety. Może być przydatny, na przykład, gdy jest używany w funkcji powłoki.

Minimalny

Funkcjonalność powyższego rozwiązania można również uzupełnić bez tworzenia procesu cut(zakładając, że echojest to wbudowana powłoka). Używa polecenia printf(zwykle wbudowanego) w nieco niejasny sposób:
stała jest całkowicie sprzedawana jako ciąg (używa formatu %s), nie ma tu zastosowania arytmetyki zmiennoprzecinkowej, więc ograniczenia floatlub doublenie mają tutaj zastosowania.
Wartość precyzji zmiany znaczenia %s( 5w poniższym przykładzie) określa długość przedrostka łańcucha do wydrukowania - która jest dokładnością. Jest 3.to część printfformatu, która chroni go przed obliczeniami dokładności.

$ printf "3.%.5s\n" 1415926535897932384626433832795 
3.14159

Alternatywa z precyzją jako oddzielny argument:

$ printf "3.%.*s\n" 5 1415926535897932384626433832795 
3.14159

Lub nieco bardziej czytelny (zwróć uwagę na spację między 3.i 14159..., to osobne argumenty):

$ printf "%s%.5s\n" 3. 1415926535897932384626433832795
3.14159

Szybki

printfMożna się spodziewać, że ten wariant będzie bardzo szybki: ponieważ printfjest powłoką wbudowaną we wspólne powłoki, takie jak bashi zsh, nie tworzy żadnych procesów.
Ponadto nie dotyka żadnego rodzaju kodu zmiennoprzecinkowego, a jedynie manipulację tablicami bajtów (wyraźnie nie znakami wielobajtowymi). Jest to zwykle szybsze, często znacznie szybsze niż użycie zmiennoprzecinkowe.

kompatybilność z printf

Często istnieją powody do zastąpienia printf, /usr/bin/printfaby zagwarantować spójność lub zgodność. W tym przypadku myślę, że możemy użyć wbudowanego - co jest ważne, ponieważ użycie /usr/bin/printfzmniejsza „szybką” przewagę poprzez rozwiązywanie procesu.
Częstym problemem związanym ze printfzgodnością jest format wyjściowy liczb w zależności od ustawień regionalnych. Oddzielanie .liczb można zmienić na ,zależne od ustawień regionalnych; Ale nie używamy liczb, a jedynie ciąg znaków zawierający literał .- na który nie ma wpływu lokalizacja.
StéphaneChazelas zwrócił na to uwagęprintf %.5s działa inaczejzsh, licząc znaki, a nie bajty jak zwykle. Na szczęście nasze stałe używają tylko znaków z dolnego zakresu ASCII, który jest kodowany przez jeden bajt na znak w dowolnym odpowiednim kodowaniu, o ile używamy wspólnego UTF-8kodowania dla Unicode, a nie kodowania o stałej szerokości.


Zauważ, że printf %.5sjest oparty na char (nie bajt) w zsh (rozsądnie, ale przeciw POSIX). ksh93„s %.5Lsopiera graphem.
Stéphane Chazelas
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.