Ini berasal dari http://programmers.blogoverflow.com/2012/08/20-controversial-programming-opinions/
"Mengingat bahwa Pi dapat diperkirakan menggunakan fungsi 4 * (1 - 1/3 + 1/5 - 1/7 + ...) dengan lebih banyak istilah yang memberikan akurasi lebih besar, tulislah fungsi yang menghitung Pi dengan akurasi 5 tempat desimal. "
- Catatan, estimasi harus dilakukan dengan menghitung urutan yang diberikan di atas.
p=lambda:3.14159
Jawaban:
JavaScript,
46 58 5645 bytePembaruan ES6 : Ternyata ada lebih banyak fitur yang tersedia bagi kami sekarang setelah lima tahun berlalu.
Versi ini ( 45 byte; ya,
let
diperlukan) bekerja dalam mode ketat ES6 dalam teori . Dalam praktiknya, Anda dapat menjalankannya di V8 (mis. Dengan simpul) dengan--use-strict --harmony-tailcalls
; fitur Proper Tailcalls belum diimplementasikan secara luas, sayangnya. Namun, itu perilaku tertentu, jadi harus baik-baik saja.Jika kita ingin tetap berpegang pada apa yang diimplementasikan secara luas, dan tidak memerlukan mode ketat, kita cukup menggunakan sintaks panah lemak ES6 untuk fungsi-fungsi tetapi mempertahankan implementasi yang sama seperti sebelumnya (disarankan oleh Brian H) dengan biaya 48 byte.
Pilihan nama untuk parameter tunggal tidak terlalu penting, tetapi kami mungkin juga memilih salah satu nama yang kami gunakan untuk meminimalkan polusi ruang lingkup global.
Versi ini adalah ekspresi fungsi; tambahkan dua karakter (mis. "
f
") jika Anda menginginkannya namanya. Versi ini mengacaukan globala
dani
; ini bisa dicegah jika kita menambahkan "a,i
" ke daftar parameter.Manfaatkan versi algoritma yang diformulasi ulang untuk menghindari kebutuhan pengurangan.
Ini versi "biasa" tanpa penyesuaian ini:
yang memiliki
6464 karakter.Terima kasih kepada @ardnew untuk saran untuk menyingkirkan
4*
sebelumreturn
.Sejarah
sumber
a+=2/i/-~-~i;return 4*a
kea+=8/i/-~-~i;return a
Python 59 byte
Ini mencetak 1000 digit; sedikit lebih dari yang dibutuhkan 5. Alih-alih menggunakan iterasi yang ditentukan, ia menggunakan ini:
Itu
6637
(yang terdalam denominator) dapat dirumuskan sebagai:Ini menyiratkan konvergensi linier. Setiap iterasi yang lebih dalam akan menghasilkan satu lagi bit biner pi .
Jika , bagaimanapun, Anda bersikeras menggunakan tan -1 identitas, konvergensi yang sama dapat dicapai, jika Anda tidak keberatan akan tentang masalah sedikit berbeda. Melihat jumlah parsial:
4.0, 2.66667, 3.46667, 2.89524, 3.33968, 2.97605, 3.28374, ...
jelas bahwa setiap istilah melompat bolak-balik ke kedua sisi titik konvergensi; seri memiliki konvergensi bolak-balik. Selain itu, setiap istilah lebih dekat ke titik konvergensi daripada istilah sebelumnya; itu benar-benar monoton sehubungan dengan titik konvergensi. Kombinasi kedua sifat ini menyiratkan bahwa rata-rata aritmatika dari dua suku tetangga lebih dekat ke titik konvergensi daripada salah satu dari istilah itu sendiri. Untuk memberi Anda gagasan yang lebih baik tentang apa yang saya maksud, pertimbangkan gambar berikut:
Seri luar adalah asli, dan seri dalam ditemukan dengan mengambil rata-rata dari masing-masing istilah tetangga. Perbedaan yang luar biasa. Tapi apa yang benar-benar luar biasa, adalah bahwa seri baru ini juga memiliki konvergensi bergantian, dan benar-benar monoton sehubungan dengan titik konvergensi. Itu berarti bahwa proses ini dapat diterapkan berulang kali, ad nauseum.
Baik. Tapi bagaimana caranya?
Beberapa definisi formal. Misalkan P 1 (n) menjadi suku ke- n dari urutan pertama, P 2 (n) menjadi suku ke- n dari urutan kedua, dan demikian pula P k (n) suku ke- n dari urutan ke- k seperti yang didefinisikan di atas .
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, ...]
Tidak mengherankan, koefisien ini mengikuti persis koefisien binomial, dan dapat dinyatakan sebagai satu baris tunggal Segitiga Pascal. Sejak baris sewenang-wenang Segitiga Pascal adalah sepele untuk menghitung, sebuah sewenang-wenang 'dalam' seri dapat ditemukan, hanya dengan mengambil pertama n parsial jumlah, kalikan masing-masing dengan istilah yang sesuai dalam k th deretan Segitiga Pascal, dan membaginya dengan 2 k-1 .
Dengan cara ini, presisi titik mengambang 32-bit penuh (~ 14 tempat desimal) dapat dicapai hanya dengan 36 iterasi, di mana titik jumlah parsial bahkan belum bertemu di tempat desimal kedua. Ini jelas bukan golf:
Jika Anda menginginkan presisi yang sewenang-wenang, ini dapat dicapai dengan sedikit modifikasi. Di sini sekali lagi menghitung 1000 digit:
Nilai awal p mulai 2 10 lebih besar, untuk menetralkan efek pembagian bilangan bulat dari s / d ketika d menjadi lebih besar, menyebabkan beberapa digit terakhir tidak bertemu. Perhatikan di sini lagi itu
3318
itu juga:Jumlah iterasi yang sama dengan algoritma pertama (dibelah dua karena t berkurang 1 bukannya 2 setiap iterasi). Sekali lagi, ini menunjukkan konvergensi linier: satu bit biner pi per iterasi. Dalam kedua kasus, 3318 iterasi diperlukan untuk menghitung 1000 digit pi , sebagai kuota sedikit lebih baik dari 1 juta iterasi untuk menghitung 5.
sumber
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)
mendekati Euler-sum Anda.P_1 = ..., P_2 = ..., P_3 = ..., P_4 = ...
, "... kalikan masing-masing dengan istilah yang sesuai dikth
baris Segitiga Pascal, dan bagi dengan2^{k-1}
.", Bukannth
baris dan2^{n-1}
?Mathematica
42 39 34 33 31 2632Pendekatan Archimedes 26 karakter
Ini mencapai kriteria ketika input 822.
Pertanyaan: Adakah yang tahu bagaimana dia menghitung Dosa 180 derajat? Bukan saya.
Pendekatan Leibniz (seri Gregory) 32 karakter
Ini adalah fungsi yang sama dengan problem poser sebagai contoh. Itu mencapai kriteria di sekitar setengah juta iterasi.
Pendekatan Madhava-Leibniz 37 karakter
Variasi ini menggunakan beberapa karakter lagi tetapi konvergen ke kriteria hanya dalam 9 iterasi!
sumber
APL (14)
sumber
--/4÷1-2×⍳1e6
Jawa (67 karakter)
Perhatikan bahwa ini menghindari hilangnya makna dengan menambahkan angka-angka dalam urutan yang benar.
sumber
while(--i>0)
kewhile(i--)
dan menyimpan 2 charsHaskell, 32
Menghitung nama fungsi itu
34
sumber
R - 25 karakter
sumber
C (GCC) (44 karakter)
Itu 41 karakter, tetapi juga harus dikompilasi
-O2
untuk mendapatkan optimiser untuk menghilangkan rekursi ekor. Ini juga bergantung pada perilaku yang tidak terdefinisi sehubungan dengan urutan++
eksekusi; terima kasih kepada ugoren karena menunjukkan ini. Saya sudah menguji dengan gcc 4.4.3 di Linux 64-bit.Perhatikan bahwa kecuali pengoptimal juga menata ulang jumlah, itu akan menambah dari jumlah terkecil, sehingga itu menghindari hilangnya signifikansi.
Sebut sebagai
p()
.sumber
q()
bukanp()
. Dan saya tidak berpikir-O2
harus dihitung (tetapi jika Anda menghitungnya, itu 4 karakter karena ruang yang diperlukan).p(0)
. 3. Simpan char denganreturn++i...
. 4. Dua++i
membuat perilaku yang tidak terdefinisi.q
- itu akan mengajarkan saya untuk memeriksa ulang setelah mengganti nama. Saya pikir saya mengikuti praktik normal dalam menghitung-O2
sebagai 3 karakter, tetapi kita bisa membukanya dengan meta jika Anda mau; meta.codegolf.stackexchange.com/questions/19 adalah satu-satunya diskusi yang relevan yang dapat saya temukan. Saya telah menambahkan versi gcc yang saya gunakan, dan yang memungkinkan saya menyebutnya sebagaip()
. Menyimpan char menghentikan optimizer dan memberikan segfault. Saya akan mengklarifikasi bahwa saya menggunakan perilaku yang tidak terdefinisi, sesuai meta.codegolf.stackexchange.com/questions/21p()
- apakah Anda yakin meneleponp()
dari konteks apa pun akan berhasil? Atau hanya apa yang terjadi pada tumpukan dalam tes Anda?p()
vsp(0)
, tapi saya tidak tahu perilaku apa yang didokumentasikan dan saya tidak benar-benar seorang programmer C.J, 26 karakter
+ / + / _ 2 ((4 _4) &%)>: +: i.100Pindah dari 100 item urutan ke 1e6 item. Juga sekarang ini adalah kode yang ditandai dan dapat disalin dari peramban ke konsol tanpa kesalahan.
sumber
-/4%>:2*i.1e6
- 13 karakter. (Terima kasih kepada b_jonas di #jsoftware untuk membuat saya menyadari bahwa-/
berfungsi menghitung jumlah dengan tanda bolak-balik. [Ini karena semua operator di J memiliki prioritas dan asosiasi yang tepat, jadi-/ 1 2 3 4
<=>1 - (2 - (3 - 4))
<=>1 - 2 + 3 - 4
.])Javascript - 33 Karakter
Panggilan
p
melewati nomor ganjil positifx
dan itu akan menghitung Pi dengan(x-1)/2
syarat.sumber
Ruby - 82 karakter
Cobalah: https://repl.it/LQ8w
Pendekatan ini menggunakan seri yang diberikan secara tidak langsung menggunakan pendekatan akselerasi numerik. Output yang dihasilkan adalah
pi ≈ 3.14159265161
vs.
pi = 3.14159265359
Dimulai dengan
Dan kemudian, karena ini bergantian, kita dapat mempercepat konvergensi menggunakan
Dan itu berulang kali menerapkan ini:
Dan untuk kesederhanaan
f(n) = f(n,n)
,.Ruby - 50 karakter
Jika Anda tidak keberatan berlari untuk waktu yang sangat lama, maka Anda bisa menggunakannya
atau
sumber
C, 69 karakter
a
diinisialisasi ke 1).void main
aneh dan tidak standar, tetapi membuat hal-hal berfungsi. Tanpa itu, rekursi diimplementasikan sebagai panggilan nyata, yang mengarah ke stack overflow. Alternatif menambahkanreturn
.4*
dapat disimpan, jika dijalankan dengan tiga parameter baris perintah.sumber
int main(a)
atau bahkanmain(a)
, GCC hanya memberikan peringatan. Dan itu akan memberikan peringatanvoid main
, dan mungkin bahkan karena Anda hanya memiliki satu argumenmain
.Clojure - 79 karakter
Ini menciptakan fungsi tanpa argumen yang akan menghitung float yang mendekati pi dengan benar ke lima tempat desimal. Perhatikan bahwa ini tidak mengikat fungsi untuk nama seperti
pi
, sehingga kode ini harus baik dievaluasi di tempat denganeval
sebagai(<code>)
atau terikat dengan nama dalam hal solusinya adalahuntuk 82 karakter
Tentang
sumber
PHP -
5655 karakterSaya tidak tahu bahwa saya bisa mendapatkannya lebih kecil tanpa melanggar aturan algoritma.
sumber
<?for(;1e6>$j;)$p+=($i=-$i|4)/~-$j+=2;echo$p;
Perl -
4339 karaktertidak yakin aturan tentang subrutin anonim, tapi inilah implementasi lain menggunakan konstruksi seri @ FireFly
sumber
Java -
9284 karakterSejauh ini saya tidak bisa mengalahkan hasil Peter Taylor, tetapi inilah milik saya:
Versi tidak disatukan:
Sunting: Menyimpan beberapa karakter menggunakan operator ternary.
sumber
Python - 56 karakter
Meh, Python-fu saya tidak cukup kuat. Saya tidak bisa melihat jalan pintas lagi, tapi mungkin pegolf yang lebih berpengalaman bisa menemukan sesuatu untuk di-trim di sini?
sumber
4.
->4
). Dalam berita lain, saya baru saja menemukan sebuah kasus di mana Python 3 sebenarnya mengalahkan Python 2 dalam kode golf!Ruby - 54 karakter
Coba pertama saya di konsol
63 karakter.
sumber
def a;
alih-alihdef a()
.Perl (76 karakter)
(Hasil: 3.14159052)
Bukan solusi sesingkat mungkin, tetapi mungkin menarik. Itu yang geometris. Saya menghitung area di bawah lingkaran.
Saya mendapat pendekatan lucu lain, tetapi sangat lambat. Ini menghitung jumlah titik diskrit dalam kotak yang berada di bawah seperempat lingkaran dan menghitung pi darinya:
Itu mengharapkan jumlah iterasi sebagai argumen baris perintah. Di sini Anda dapat melihat bagaimana run time terkait dengan akurasi. ;)
sumber
k (25 karakter)
4 * + /% (i # 1 -1) '1 + 2 ! I: 1000000Sedikit lebih pendek:
sumber
Python (49)
sumber
CJam - 21
Perhitungan yang cukup mudah dari seri yang diberikan.
CJam adalah http://sf.net/p/cjam
sumber
Julia - 30 karakter
sumber
SQL, 253 byte
Saya akan memberikan SQL Fiddle, tetapi ini terlalu banyak loop menemukan fraksi 1/3 1/5 1/7 dll dan memberikan kesalahan lol. Namun, jika Anda mengubah
@B<100000
untuk1000
kemudian berjalan (jelas tidak dengan jumlah yang sama digit akurasi).sumber
Befunge, 129 byte
Cobalah online!
Jika ada yang bertanya-tanya, itu adalah gajah.
sumber