Estimator Monte Carlo dari Pi

25

Selamat Hari Pi semuanya! Tanpa alasan sama sekali, saya mencoba membuat estimator Pi Carlo yang sesingkat mungkin dari Monte Carlo. Bisakah kita membuat satu yang bisa muat dalam tweet?

Untuk memperjelas, apa yang ada dalam pikiran saya adalah pendekatan khas menggambar titik acak dari satuan kuadrat dan menghitung rasio yang termasuk dalam lingkaran satuan. Jumlah sampel dapat berupa kode keras atau tidak. Jika Anda melakukan hardcode pada mereka, Anda harus menggunakan setidaknya 1000 sampel. Hasilnya dapat dikembalikan atau dicetak sebagai titik mengambang, titik tetap atau angka rasional.

Tidak ada fungsi trigonometri atau konstanta Pi, harus merupakan pendekatan Monte Carlo.

Ini adalah kode golf, jadi pengiriman terpendek (dalam byte) menang.

keegan
sumber
2
apakah fungsi trigonometri diizinkan? Saya sarankan Anda secara eksplisit melarang mereka.
Level River St
((0..4e9).map{rand**2+rand**2<1}.to_s.sub(/./,"$1.")
John Dvorak
@ JanDvorak Bagaimana itu seharusnya bekerja? Bukankah itu mapmemberi Anda array truedan false?
Martin Ender
@ MartinBüttner Ah, oops, maaf. .filter{...}.sizeharus bekerja.
John Dvorak
@JanDvorak Memang. Itu sangat rapi :)
Martin Ender

Jawaban:

17

80386 kode mesin, 40 38 byte

Hexdump kode:

60 33 db 51 0f c7 f0 f7 e0 52 0f c7 f0 f7 e0 58
03 d0 72 03 83 c3 04 e2 eb 53 db 04 24 58 db 04
24 58 de f9 61 c3

Cara mendapatkan kode ini (dari bahasa assembly):

    // ecx = n (number of iterations)
    pushad;
    xor ebx, ebx; // counter
    push ecx; // save n for later
myloop:
    rdrand eax; // make a random number x (range 0...2^32)
    mul eax; // calculate x^2 / 2^32
    push edx;
    rdrand eax; // make another random number y
    mul eax; // calculate y^2 / 2^32
    pop eax;
    add edx, eax; // calculate D = x^2+y^2 / 2^32 (range 0...2^33)
    jc skip; // skip the following if outside the circle
    add ebx, 4; // accumulate the result multiplied by 4
skip:
    loop myloop;
    push ebx; // convert the result
    fild dword ptr [esp]; // to floating-point
    pop eax;
    fild dword ptr [esp]; // convert n to floating-point
    pop eax;
    fdivp st(1), st; // divide

    popad;
    ret;

Ini adalah fungsi menggunakan fastcallkonvensi pemanggilan MS (jumlah iterasi diteruskan dalam register ecx). Ini mengembalikan hasil dalam stregister.

Hal-hal menyenangkan tentang kode ini:

  • rdrand - hanya 3 byte untuk menghasilkan angka acak!
  • Ia menggunakan (tidak ditandatangani) integer aritmatika hingga pembagian akhir.
  • Perbandingan jarak kuadrat ( D) dengan jari-jari kuadrat ( 2^32) dilakukan secara otomatis - bendera carry berisi hasilnya.
  • Untuk mengalikan jumlah dengan 4, itu menghitung sampel dalam langkah 4.
anatolyg
sumber
Komentar harus berbunyi "Hitung x ^ 2% 2 ^ 32"
Cole Johnson
@ColeJohnson Tidak - nomor acak ada di eax; yang mulkelipatan perintah itu dengan sendirinya dan menempatkan bagian tinggi di edx; bagian rendah dalam eaxdibuang.
anatolyg
11

Matlab / Oktaf, 27 byte

Saya tahu sudah ada jawaban Matlab / Oktaf, tapi saya mencoba pendekatan saya sendiri. Saya menggunakan fakta bahwa integral 4/(1+x^2)antara 0 dan 1 adalah pi.

mean(4./(1+rand(1,1e5).^2))
cacat
sumber
Algoritme yang berbeda selalu luar biasa! Juga lebih efisien!
anatolyg
7

R, 40 (atau 28 atau 24 menggunakan metode lain)

mean(4*replicate(1e5,sum(runif(2)^2)<1))

mean(4*sqrt(1-runif(1e7)^2))

mean(4/(1+runif(1e7)^2))

Python 2, 56

Satu lagi Python, jika numpy diperbolehkan, tetapi sangat mirip dengan Matlab / Oktaf:

import numpy;sum(sum(numpy.random.rand(2,8e5)**2)<1)/2e5
Mat
sumber
6

Mathematica, 42 40 39 byte (atau 31/29?)

Saya punya tiga solusi semuanya pada 42 byte:

4Count[1~RandomReal~{#,2},p_/;Norm@p<1]/#&
4Tr@Ceiling[1-Norm/@1~RandomReal~{#,2}]/#&
4Tr@Round[1.5-Norm/@1~RandomReal~{#,2}]/#&

Mereka semua adalah fungsi yang tidak disebutkan namanya yang mengambil jumlah sampel dan nmengembalikan rasional mendekati π. Pertama-tama mereka semua menghasilkan npoin di unit square di kuadran positif. Kemudian mereka menentukan jumlah sampel yang terletak di dalam lingkaran satuan, dan kemudian mereka membaginya dengan jumlah sampel dan mengalikannya dengan 4. Satu-satunya perbedaan adalah bagaimana mereka menentukan jumlah sampel di dalam lingkaran unit:

  • Yang pertama menggunakan Countdengan syarat itu Norm[p] < 1.
  • Yang kedua mengurangi norma dari setiap titik dari 1dan kemudian mengumpulkan. Ini mengubah angka di dalam lingkaran unit ke 1dan yang di luar 0. Setelah itu saya jumlahkan semuanya Tr.
  • Yang ketiga tidak dasarnya sama, tetapi mengurangi dari 1.5, sehingga saya dapat menggunakan Roundbukan Ceiling.

Aaaaaand saat menulis ini, terpikir oleh saya bahwa memang ada solusi yang lebih pendek, jika saya hanya mengurangi 2dan kemudian menggunakan Floor:

4Tr@Floor[2-Norm/@1~RandomReal~{#,2}]/#&

atau menyimpan byte lain dengan menggunakan lantai Unicode atau operator langit-langit:

4Tr@⌊2-Norm/@1~RandomReal~{#,2}⌋/#&
4Tr@⌈1-Norm/@1~RandomReal~{#,2}⌉/#&

Perhatikan bahwa tiga solusi berbasis pembulatan juga dapat ditulis dengan Meanbukan Trdan tanpa /#, lagi untuk byte yang sama.


Jika pendekatan berbasis Monte Carlo lainnya baik-baik saja (khususnya, yang dipilih Peter), saya dapat melakukan 31 byte dengan memperkirakan integral atau 29 menggunakan integral , kali ini diberikan sebagai angka floating point:√(1-x2)1/(1+x2)

4Mean@Sqrt[1-1~RandomReal~#^2]&
Mean[4/(1+1~RandomReal~#^2)]&
Martin Ender
sumber
9
Anda punya tiga solusi untuk kehidupan, alam semesta dan segalanya dan Anda memutuskan untuk merusaknya? Bidaah.
seequ
6

CJam, 27 23 22 atau 20 byte

4rd__{{1dmr}2*mhi-}*//

2 byte disimpan berkat Runner112, 1 byte disimpan berkat Sp3000

Dibutuhkan jumlah iterasi dari STDIN sebagai input.

Ini lurus ke depan karena mendapat. Ini adalah langkah-langkah utama yang terlibat:

  • Baca input dan jalankan iterasi Monte Carlo berkali-kali
  • Di setiap iterasi, dapatkan jumlah kuadrat dari dua float acak dari 0 hingga 1 dan lihat apakah kurang dari 1
  • Dapatkan rasio berapa kali kami mendapat kurang dari 1 dengan iterasi total dan kalikan dengan 4 untuk mendapatkan PI

Perluasan kode :

4rd                     "Put 4 on stack, read input and convert it to a double";
   __{            }*    "Take two copies, one of them determines the iteration"
                        "count for this code block";
      {1dmr}2*          "Generate 2 random doubles from 0 to 1 and put them on stack";
              mh        "Take hypot (sqrt(x^2 + y^2)) where x & y are the above two numbers";
                i       "Convert the hypot to 0 if its less than 1, 1 otherwise";
                 -      "Subtract it from the total sum of input (the first copy of input)";
                    //  "This is essentially taking the ratio of iterations where hypot";
                        "is less than 1 by total iterations and then multiplying by 4";

Cobalah online di sini


Jika nilai rata-rata 1/(1+x^2)juga dianggap sebagai Monte Carlo, maka ini dapat dilakukan dalam 20 byte:

Urd:K{4Xdmr_*)/+}*K/

Coba di sini

Pengoptimal
sumber
2
Saya mencoba jawaban CJam juga, dan berhasil datang dalam 2 byte di bawah skor Anda. Tapi kode saya keluar sangat mirip dengan Anda, saya merasa kotor mempostingnya sebagai jawaban terpisah. Semuanya sama kecuali untuk pilihan variabel dan dua optimasi ini: dapatkan angka acak dari 0 hingga 1 dengan 1dmrbukan KmrK/, dan periksa apakah jumlah kuadrat lebih besar dari 1 dengan ialih - alih 1>(saya pikir yang ini sangat pintar) .
Runer112
@ Runer112 Terima kasih. yang itrik benar-benar rapi! Dan sialnya kurangnya dokumentasi untuk1dmr
Pengoptimal
5

Python 2, 77 75 byte

from random import*;r=random;a=0;exec"a+=r()**2+r()**2<1;"*4000;print a/1e3

Menggunakan 4000 sampel untuk menghemat byte 1e3.

Sp3000
sumber
5
Anda bisa mendapatkan akurasi lebih sedikit tanpa biaya dengan ...*8000;print a/2e3.
Logic Knight
5

Commodore 64 Basic, 45 byte

1F┌I=1TO1E3:C=C-(R/(1)↑2+R/(1)↑2<1):N─:?C/250

Pergantian PETSCII: = SHIFT+E, /= SHIFT+N, =SHIFT+O

Menghasilkan 1000 poin di kuadran pertama; untuk masing-masing, tambahkan kebenaran "x ^ 2 + y ^ 2 <1" ke hitungan berjalan, lalu bagi hitungan dengan 250 untuk mendapatkan pi. (Kehadiran tanda minus karena pada C64, "true" = -1.)

Menandai
sumber
Apa yang (1)harus dilakukan
echristopherson
@echristopherson, Anda salah membaca. /bukan simbol pembagian, itu karakter yang dihasilkan dengan mengetik SHIFT+Npada keyboard Commodore 64. R/(1)adalah cara pintas untuk RND(1), yaitu. + msgstr "menghasilkan angka acak antara 0 dan 1 menggunakan seed RNG saat ini".
Mark
Oh kamu benar! Karakter grafik PETSCII tua yang bagus.
echristopherson
5

J, 17 byte

Menghitung nilai rata-rata dari 40000nilai sampel fungsi 4*sqrt(1-sqr(x))dalam rentang [0,1].

Dengan mudah 0 o.xkembali sqrt(1-sqr(x)).

   1e4%~+/0 o.?4e4$0
3.14915
randomra
sumber
4

> <> (Ikan) , 114 byte

:00[2>d1[   01v
1-:?!vr:@>x|  >r
c]~$~< |+!/$2*^.3
 .41~/?:-1r
|]:*!r$:*+! \
r+)*: *:*8 8/v?:-1
;n*4, $-{:~ /\r10.

Sekarang,> <> tidak memiliki generator angka acak bawaan. Namun ia memiliki fungsi yang mengirimkan pointer ke arah acak. Penghasil angka acak dalam kode saya:

______d1[   01v
1-:?!vr:@>x|  >r
_]~$~< |+!/$2*^__
 __________
___________ _
_____ ____ _______
_____ ____~ ______

Ini pada dasarnya menghasilkan bit acak yang membentuk angka biner dan kemudian mengonversi angka biner acak itu menjadi desimal.

Sisanya hanyalah poin reguler dalam pendekatan kuadrat.

Penggunaan: ketika Anda menjalankan kode Anda harus memastikan untuk mengisi ulang tumpukan (-v dalam python interpreter) dengan jumlah sampel, misalnya

pi.fish -v 1000

kembali

3.164
cirpis
sumber
4

Matlab atau Oktaf 29 byte (terima kasih kepada flawr!)

mean(sum(rand(2,4e6).^2)<1)*4

(Saya tidak yakin apakah <1 baik-baik saja. Saya membacanya harus <= 1. Tapi seberapa besar probabilitas untuk menggambar tepat 1 ...)

Matlab atau Oktaf 31 byte

sum(sum(rand(2,4e3).^2)<=1)/1e3
Steffen
sumber
1
Ide yang sangat bagus! Anda dapat menyimpan dua byte tambahan dengan mean(sum(rand(2,4e6).^2)<1)*4.
flawr
4

Java, 108 byte

double π(){double π=0,x,i=0;for(;i++<4e5;)π+=(x=Math.random())*x+(x=Math.random())*x<1?1e-5:0;return π;}

Empat ribu iterasi, menambahkan 0,001 setiap kali titik berada di dalam lingkaran unit. Hal-hal yang cukup mendasar.

Catatan: Ya, saya tahu saya bisa menumpahkan empat byte dengan mengubah πke karakter byte tunggal. Saya suka seperti ini.

Geobit
sumber
mengapa tidak 9999 iterasi?
Pengoptimal
1
@Optimizer Ini membuat jumlahnya lebih pendek. Untuk iterasi 9999, saya harus menambahkan angka yang lebih tepat setiap kali, yang biayanya digit.
Geobits
1
Anda dapat menyimpan byte lain dan meningkatkan presisi dengan menggunakan "4e5" dan "1e-5" untuk angka-angkanya.
Vilmantas Baranauskas
@VilmantasBaranauskas Terima kasih! Saya selalu lupa tentang hal itu :) Menggoda untuk menggunakan 4e9 dan 1e-9 sebagai gantinya, tapi itu butuh waktu cukup lama ...
Geobits
Protip: saat bermain golf, Anda harus benar-benar mengurangi byte, bukan meningkatkannya secara artifisial
Destructible Lemon
3

Javascript: 62 Bytes

for(r=Math.random,t=c=8e4;t--;c-=r()**2+r()**2|0);alert(c/2e4)

Saya menggunakan jawaban javascript sebelumnya (sekarang dihapus) dan mencukur 5 byte.

Guzman Tierno
sumber
Anda dapat menautkan ke jawaban cfern untuk memberikan kredit dengan benar.
Jonathan Frech
Jawaban Anda tampaknya menjadi potongan yang dianulir I / O . Harap perbaiki atau hapus posting Anda.
Jonathan Frech
Maaf, saya baru, saya tidak tahu cara menempatkan tautan ke solusi sebelumnya yang sekarang muncul telah dihapus. Mengenai cuplikan: Saya sepenuhnya setuju, tetapi itu adalah kode dari solusi javascript sebelumnya yang saya juga pikir itu tidak valid karena alasan itu. Saya memodifikasi tambang saya menjadi sebuah program.
Guzman Tierno
Iya nih; jawaban sebelumnya dihapus karena tidak valid - saya melihat jawaban Anda sebelum saya merekomendasikan penghapusan, demikian komentarnya. +1 untuk mengirimkan jawaban yang valid; selamat datang di PPCG!
Jonathan Frech
2

GolfScript (34 karakter)

0{^3?^rand.*^.*+/+}2000:^*`1/('.'@

Demo online

Ini menggunakan titik tetap karena GS tidak benar-benar memiliki titik mengambang. Ini sedikit menyalahgunakan penggunaan titik tetap, jadi jika Anda ingin mengubah jumlah iterasi pastikan itu dua kali kekuatan sepuluh.

Kredit kepada xnor untuk metode Monte Carlo tertentu yang digunakan.

Peter Taylor
sumber
2

Python 2, 90 85 81 byte

from random import*;r=random;print sum(4.for i in[0]*9**7if r()**2+r()**2<1)/9**7

kembali 3.14120037157misalnya. Jumlah sampel adalah 4782969 (9 ^ 7). Anda bisa mendapatkan pi yang lebih baik dengan 9 ^ 9 tetapi Anda harus bersabar.

Ksatria Logika
sumber
Anda dapat menyimpan 3 dengan mengganti range(9**7)dengan [0]*9**7atau sesuatu, karena Anda tidak menggunakannya i. Dan daftarnya tidak terlalu lama untuk mengalami masalah memori.
Sp3000
Terima kasih. Saya ingin menyingkirkan range()tetapi saya benar-benar lupa trik itu.
Logic Knight
Saya punya perasaan [0]9**7bukan sintaks yang valid.
seequ
Kamu benar. Saya telah memasang kembali asterix yang hilang (ada di bawah meja saya).
Logic Knight
2

Ruby, 39 byte

p (1..8e5).count{rand**2+rand**2<1}/2e5

Salah satu yang menonjol adalah bahwa ini dapat menggunakan 8e5notasi, yang membuatnya dapat diperpanjang hingga ~ 8e9 sampel dalam jumlah byte program yang sama.

GreyCat
sumber
2

Perl 6 , 33 byte

{4*sum((1>rand²+rand²)xx$_)/$_}

Cobalah online!

Ini adalah fungsi yang mengambil jumlah sampel sebagai argumen.

Sean
sumber
1

Scala, 87 77 66 byte

def s=math.pow(math.random,2);Seq.fill(1000)(s+s).count(_<1)/250d
keegan
sumber
Jika Anda mengganti 1000dengan 8000dan 250ddengan 2e4Anda berdua menghemat satu byte dan menambah jumlah sampel dengan faktor 8.
Dave Swartz
1

Bash Murni, 65 byte

for((;i++<$1*4;a+=RANDOM**2+RANDOM**2<32767**2));{ :;}
echo $a/$1

Mengambil parameter baris perintah tunggal yang dikalikan dengan 4 untuk memberikan jumlah sampel. Bash arithmetic adalah bilangan bulat saja, jadi rasional adalah output. Ini dapat disalurkan ke bc -luntuk divisi terakhir:

$ ./montepi.sh 10000
31477/10000
$ ./montepi.sh 10000|bc -l
3.13410000000000000000
$ 
Trauma Digital
sumber
1

Joe , 20 19 byte

Catatan: jawaban ini tidak bersaing, karena versi 0.1.2, yang menambahkan keacakan, dirilis setelah tantangan ini.

Dinamakan fungsi F:

:%$,(4*/+1>/+*,?2~;

Fungsi yang tidak disebutkan namanya:

%$,(4*/+1>/+*,?2~;)

Keduanya mengambil jumlah sampel sebagai argumen dan mengembalikan hasilnya. Bagaimana mereka bekerja?

%$,(4*/+1>/+*,?2~;)
   (4*/+1>/+*,?2~;) defines a chain, where functions are called right-to-left
               2~;  appends 2 to the argument, giving [x, 2]
              ?     create a table of random values from 0 to 1 with that shape
            *,      take square of every value
          /+         sum rows, giving a list of (x**2+y**2) values
        1>           check if a value is less than 1, per atom
      /+             sum the results
    4*               multiply by four
%$,                  divide the result by the original parameter

Contoh berjalan:

   :%$,(4*/+1>/+*,?2~;
   F400000
3.14154
   F400000
3.14302
seequ
sumber
1

dc, 59 karakter (spasi kosong diabaikan)

[? 2^ ? 2^ + 1>i]su
[lx 1+ sx]si
[lu x lm 1+ d sm ln>z]sz

5k
?sn
lzx
lx ln / 4* p
q

Saya mengujinya pada Plan 9 dan OpenBSD, jadi saya bayangkan ini akan bekerja di Linux (GNU?) dc.

Penjelasan demi baris:

  1. Menyimpan kode ke [baca dan beri dua float; jalankan register ijika 1 lebih besar dari jumlah kuadratnya] dalam register u.
  2. Menyimpan kode ke [register bertambah x1] di register i.
  3. Menyimpan kode untuk [menjalankan register u, menambah register m, dan kemudian menjalankan register zjika register mlebih besar dari register n] dalam register z.
  4. Atur skala ke 5 poin desimal.

  5. Baca jumlah poin untuk sampel dari baris input pertama.
  6. Jalankan register z.
  7. Bagi register x(jumlah hit) dengan register n(jumlah poin), kalikan hasilnya dengan 4, dan cetak.
  8. Berhenti.

Namun, saya curang:

Program ini membutuhkan persediaan float acak antara 0 dan 1.

/* frand.c */
#include <u.h>
#include <libc.h>

void
main(void)
{
    srand(time(0));

    for(;;)
        print("%f\n", frand());
}

Pemakaian:

#!/bin/rc
# runpi <number of samples>

{ echo $1; frand } | dc pi.dc

Uji coba:

% runpi 10000
3.14840

Sekarang dengan lebih sedikit kecurangan (100 byte)

Seseorang menunjukkan bahwa saya dapat memasukkan prng sederhana.
http://en.wikipedia.org/wiki/RANDU

[lrx2^lrx2^+1>i]su[lx1+sx]si[luxlm1+dsmln>z]sz[0kls65539*2 31^%dsslkk2 31^/]sr?sn5dksk1sslzxlxlm/4*p

Tidak disatukan

[
Registers:
u - routine : execute i if sum of squares less than 1
i - routine : increment register x
z - routine : iterator - execute u while n > m++
r - routine : RANDU PRNG
m - variable: number of samples
x - variable: number of samples inside circle
s - variable: seed for r
k - variable: scale for division
n - variable: number of iterations (user input)
]c
[lrx 2^ lrx 2^ + 1>i]su
[lx 1+ sx]si
[lu x lm 1+ d sm ln>z]sz
[0k ls 65539 * 2 31^ % d ss lkk 2 31 ^ /]sr
? sn
5dksk
1 ss
lzx
lx lm / 4*
p

Uji coba:

$ echo 10000 | dc pigolf.dc
3.13640
progrider42
sumber
1

Pyth, 19

c*4sm<sm^OQ2 2*QQQQ

Berikan jumlah iterasi yang diinginkan sebagai input.

Demonstrasi

Karena Pyth tidak memiliki fungsi "Angka mengambang acak", saya harus berimprovisasi. Program memilih dua bilangan bulat positif acak kurang dari input, kuadrat, jumlah, dan dibandingkan dengan input kuadrat. Ini dilakukan beberapa kali sama dengan input, kemudian hasilnya dikalikan dengan 4 dan dibagi dengan input.

Dalam berita terkait, saya akan menambahkan operasi nomor floating point acak ke Pyth segera. Namun, program ini tidak menggunakan fitur itu.


Jika kita menafsirkan "Hasilnya dapat dikembalikan atau dicetak sebagai titik mengambang, titik tetap atau angka rasional." secara bebas, kemudian mencetak pembilang dan penyebut dari fraksi yang dihasilkan harus cukup. Dalam hal itu:

Pyth, 18

*4sm<sm^OQ2 2*QQQQ

Ini adalah program yang identik, dengan operasi pembagian titik mengambang ( c) dihapus.

isaacg
sumber
1

Julia, 37 byte

4mean(1-floor(sum(rand(4^8,2).^2,2)))

Jumlah sampel adalah 65536 (= 4 ^ 8).

Varian yang sedikit lebih panjang: fungsi dengan jumlah sampel ssebagai satu-satunya argumen:

s->4mean(1-floor(sum(rand(s,2).^2,2)))
pawel.boczarski
sumber
1

C, 130 byte

#include<stdlib.h>f(){double x,y,c=0;for(int i=0;i<8e6;++i)x=rand(),y=rand(),c+=x*x+y*y<1.0*RAND_MAX*RAND_MAX;printf("%f",c/2e6);}

Tidak Disatukan:

#include <stdlib.h>
f(){
 double x,y,c=0;
 for(int i=0; i<8e6; ++i) x=rand(), y=rand(), c+=x*x+y*y<1.0*RAND_MAX*RAND_MAX;
 printf("%f",c/2e6);
}
Karl Napf
sumber
tentu saja, Anda mungkin masih harus memposting versi tersebut tanpa spasi putih (pertahankan versi saat ini dengan tajuk "ungolfed / with whitespace" atau sesuatu)
Destructible Lemon
@DestructibleWatermelon selesai!
Karl Napf
Solusinya tidak bekerja di GCC tanpa baris baru sebelumnya f(). Kompiler apa yang Anda gunakan? Lihat tio.run/##Pc49C4JAHIDx3U9xGMG9ZdYgwWkgtNbQ1BZ6L/UHO8M07hA/…
eush77
101 bytes
ceilingcat
1

Sebenarnya , 14 byte (tidak bersaing)

`G²G²+1>`nkæ4*

Cobalah online!

Solusi ini tidak bersaing karena bahasa tersebut mengesampingkan tantangan. Jumlah sampel diberikan sebagai input (bukan kode keras).

Penjelasan:

`G²G²+1>`nkæ4*
`G²G²+1>`n      do the following N times:
 G²G²+            rand()**2 + rand()**2
      1>          is 1 greater?
          kæ    mean of results
            4*  multiply by 4
Mego
sumber
2
Mengapa downvote?
Destructible Lemon
1

Racket 63 byte

Menggunakan metode jawaban bahasa R oleh @Matt:

(/(for/sum((i n))(define a(/(random 11)10))(/ 4(+ 1(* a a))))n)

Tidak Disatukan:

(define(f n)
   (/
    (for/sum ((i n))
      (define a (/(random 11)10))
      (/ 4(+ 1(* a a))))
    n))

Pengujian:

(f 10000)

Output (fraksi):

3 31491308966059784/243801776017028125

Sebagai desimal:

(exact->inexact(f 10000))

3.13583200307849
juga
sumber
1

Fortran (GFortran) , 84 83 byte

CALL SRAND(0)
DO I=1,4E3
X=RAND()
Y=RAND()
IF(X*X+Y*Y<1)A=A+1E-3
ENDDO
PRINT*,A
END

Cobalah online!

Kode ini sangat buruk aja. Ini akan gagal jika gfortran memutuskan untuk menginisialisasi variabel Adengan nilai lain kemudian 0 (yang terjadi 50% dari kompilasi, kira-kira) dan, jika Adiinisialisasi sebagai 0, itu akan selalu menghasilkan urutan acak yang sama untuk seed yang diberikan. Kemudian, nilai yang sama untuk Pi dicetak selalu.

Ini adalah program yang jauh lebih baik:

Fortran (GFortran) , 100 99 byte

A=0
DO I=1,4E3
CALL RANDOM_NUMBER(X)
CALL RANDOM_NUMBER(Y)
IF(X*X+Y*Y<1)A=A+1E-3
ENDDO
PRINT*,A
END

Cobalah online!

(Satu byte disimpan di setiap versi; terima kasih Penguino).

rafa11111
sumber
1
Di setiap versi Anda dapat menyimpan byte dengan mengubah 'DO I = 1,1E3' menjadi 'DO I = 1,4E3', mengubah 'A = A + 1' menjadi 'A = A + 1E-3', dan mengubah ' PRINT *, A / 250 'ke' PRINT *, A '
Penguino
Ya kamu yakin! Terima kasih atas sarannya!
rafa11111
1

Japt , 26 atau 18 byte

o r_+ÂMhMr p +Mr p <1Ã*4/U

Cobalah online!

Analog dengan jawaban Pengoptimal , terutama hanya mencoba mempelajari Japt.
Mengambil jumlah iterasi untuk dijalankan sebagai input implisit U.

o                           Take the input and turn it into a range [0, U),
                            essentially a cheap way to get a large array.
  r_                        Reduce it with the default initial value of 0.
    +Â                      On each iteration, add one if
      MhMr p +Mr p          the hypotenuse of a random [0,1)x[0,1) right triangle
                   <1       is smaller than one.
                     Ã*4/U  Multiply the whole result by four and divide by input.

Jika 1/(1+x^2)diizinkan (alih-alih dua random terpisah), maka kita dapat mencapai 18 byte dengan logika yang sama.

o r_Ä/(1+Mr pÃ*4/U
Nit
sumber
1
Anda dapat menyimpan beberapa byte dengan membiarkan Mhmenghitung sisi miring daripada melakukannya sendiri ;-) Selain itu, Anda dapat menggunakan xuntuk mengambil jumlah array, daripada mengurangi dengan menambahkan:o x@MhMr Mr)<1Ã*4/U
ETHproductions
@ ETHproductions Rapi, saya tidak tahu Anda bisa menggunakan Mhseperti itu, terima kasih! Jawaban dua-acak Anda hampir sependek jawaban saya dengan hanya satu acak, itu cukup keren. Saya akan xingat, saya cenderung menggunakan pengurangan banyak saat mencoba golf, jadi ini akan sangat berguna.
Nit
1

F #, 149 byte

open System;
let r=new Random()
let q()=
 let b=r.NextDouble()
 b*b
let m(s:float)=(s-Seq.sumBy(fun x->q()+q()|>Math.Sqrt|>Math.Floor)[1.0..s])*4.0/s

Cobalah online!

Sejauh yang saya bisa tahu, untuk melakukan ini total berjalan di F # lebih pendek untuk membuat array angka dan menggunakan Seq.sumBymetode daripada menggunakan for..to..doblok.

Apa yang dilakukan kode ini yaitu membuat kumpulan angka floating-point dari 1 hingga s, melakukan fungsi fun x->...untuk jumlah elemen dalam koleksi, dan menjumlahkan hasilnya. Ada selemen dalam koleksi, jadi tes acak dilakukan skali. Angka-angka aktual dalam koleksi diabaikan ( fun x->, tetapi xtidak digunakan).

Ini juga berarti bahwa aplikasi harus terlebih dahulu membuat dan mengisi array, dan kemudian beralih di atasnya. Jadi itu mungkin dua kali lebih lambat dari for..to..doloop. Dan dengan penggunaan array penciptaan memori di wilayah O (f ** k)!

Untuk tes yang sebenarnya itu sendiri, alih-alih menggunakan if then elsepernyataan apa yang dilakukannya adalah menghitung jarak ( q()+q()|>Math.Sqrt) dan membulatkannya ke bawah Math.Floor. Jika jarak di dalam lingkaran, itu akan dibulatkan ke 0. Jika jarak di luar lingkaran itu akan dibulatkan ke 1. Seq.sumByMetode kemudian akan total hasil ini.

Perhatikan bahwa yang Seq.sumBytelah dijumlahkan bukanlah titik di dalam lingkaran, tetapi titik di luarnya . Jadi untuk hasilnya dibutuhkan s(ukuran sampel kami) dan kurangi total dari itu.

Tampaknya juga bahwa mengambil ukuran sampel sebagai parameter lebih pendek daripada mengkodekan nilainya. Jadi saya selingkuh sedikit ...

Ciaran_McCarthy
sumber
1

Haskell, 116 114 110 96 byte

d=8^9
g[a,b]=sum[4|a*a+b*b<d*d]
p n=(sum.take(floor n)$g<$>iterate((\x->mod(9*x+1)d)<$>)[0,6])/n

Karena berurusan dengan import System.Random; r=randoms(mkStdGen 2)akan mengambil terlalu banyak byte yang berharga, saya menghasilkan daftar angka acak tak terbatas dengan generator kongruensi linear yang beberapa orang katakan hampir kuat secara kriptografis:, x↦x*9+1 mod 8^9yang oleh Teorema Hull-Dobell memiliki periode penuh 8^9.

gmenghasilkan 4jika titik angka acak berada di dalam lingkaran untuk pasangan angka acak [0..8^9-1]karena ini menghilangkan perkalian dalam rumus yang digunakan.

Pemakaian:

> p 100000
3.14208

Cobalah online!

Angs
sumber
1

Perl 5, 34 byte

$_=$a/map$a+=4/(1+(rand)**2),1..$_

Jumlah sampel diambil dari stdin. Membutuhkan -p.

Berfungsi karena:

Cobalah online!

primo
sumber