Pi'nin Monte Carlo tahmincisi


25

Pi Gününüz kutlu olsun millet! Sebepsiz yere, mümkün olduğunca kısa Pi'nin Monte Carlo tahmincisini oluşturmaya çalışıyorum. Bir tweet'e uyan bir tane yapabilir miyiz?

Açıkçası, aklımdaki şey, birim kareden rastgele noktalar çizmenin ve birim çemberin içine düşen oranı hesaplamanın tipik bir yaklaşımıdır. Örneklerin sayısı kodlanmış olabilir veya olmayabilir. Bunları kodlarsanız, en az 1000 örnek kullanmanız gerekir. Sonuç, kayan nokta, sabit nokta veya rasyonel sayı olarak döndürülebilir veya yazdırılabilir.

Hiçbir trig fonksiyonu veya Pi sabiti, Monte Carlo yaklaşımı olmamalıdır.

Bu kod golf, yani en kısa gönderme (bayt cinsinden) kazanır.


2
trig fonksiyonlarına izin verilir mi? Onları açıkça yasaklamanı öneririm.
Seviye Nehri St

((0..4e9).map{rand**2+rand**2<1}.to_s.sub(/./,"$1.")
John Dvorak

@JanDvorak Nasıl çalışması gerekiyor? Does not mapsize bir dizi vermek trueve false?
Martin Ender

@ MartinBüttner Ah, üzgünüz. .filter{...}.sizeçalışması gerekir.
John Dvorak

@JanDvorak Gerçekten. Bu gerçekten çok temiz :)
Martin Ender

Yanıtlar:


17

80386 makine kodu, 40 38 bayt

Kodun Hexdump:

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

Bu kod nasıl alınır (assembly dilinde):

    // 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;

Bu, MS fastcallçağrı kuralını kullanan bir fonksiyondur (yineleme sayısı kayıt defterinde iletilir ecx). Kayıttaki sonucu döndürür st.

Bu kod hakkında eğlenceli şeyler:

  • rdrand - rastgele bir sayı üretmek için sadece 3 bayt!
  • Son bölüme kadar (işaretsiz) tamsayı aritmetiği kullanır.
  • Kare mesafesi ( D) ile kare yarıçapı ( 2^32) karşılaştırması otomatik olarak yapılır - taşıma bayrağı sonucu içerir.
  • Sayımı 4 ile çarpmak için 4 adımda örnekleri sayar.

Yorum okumalısınız "Hesapla x ^ 2% 2 ^ 32"
Cole Johnson

@ColeJohnson Hayır - rasgele sayı içinde eax; mulkendisi ve koyar yüksek kısmını tarafından komuta katları bunu edx; içindeki düşük kısım eaxatılır.
anatolyg

11

Matlab / Octave, 27 bayt

Çoktan bir Matlab / Octave cevabı olduğunu biliyorum ama kendi yaklaşımımı denedim. 4/(1+x^2)0 ile 1 arasındaki integralin pi olduğu gerçeğini kullandım .

mean(4./(1+rand(1,1e5).^2))

Farklı bir algoritma her zaman mükemmeldir! Ayrıca, daha verimli!
anatolyg

7

R, 40 (veya başka yöntemler kullanarak 28 veya 24)

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

Uyuşukluğa izin veriliyorsa, ancak Matlab / Octave ile oldukça benzer olan bir başka Python:

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

6

Mathematica, 42 40 39 bayt (veya 31/29?)

42 baytta üç çözümüm var:

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

Bunların hepsi örnek sayısını alan nve tional rasyonel bir rasyon yaklaşımı veren isimsiz fonksiyonlardır . Öncelikle, hepsi npozitif kadranda ünite karesinde noktalar oluşturur . Sonra birim çemberin içinde kalan örneklerin sayısını belirler ve ardından örneklerin sayısına bölün ve çarpılır 4. Tek fark, ünite çemberindeki örneklerin sayısını nasıl belirledikleridir:

  • İlki Countbu şartla kullanır Norm[p] < 1.
  • İkincisi, her bir noktanın normunu çıkarır 1ve sonra yuvarlar. Bu, ünite dairesi içindeki sayıları 1ve dışındakileri döndürür 0. Daha sonra hepsini özetleyeceğim Tr.
  • Üçüncüsü esas olarak aynısını yapar, ancak onu çıkarır 1.5, böylece Roundyerine kullanabilirim Ceiling.

Aaaaaand bunu yazarken, eğer sadece çıkarır 2ve sonra kullanırsam , gerçekten daha kısa bir çözüm olduğu aklıma geldi Floor:

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

veya Unicode döşeme veya tavan operatörlerini kullanarak başka bir bayttan tasarruf etmek:

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

Üç yuvarlama tabanlı çözümün , aynı baytlar için tekrar Meanyerine Trve olmadan yazılabileceğini unutmayın /#.


Monte Carlo temelli diğer yaklaşımlar iyi ise (özellikle Peter'ın seçtiği) , bu kez kayan nokta sayısı olarak verilen integralini veya 29 değerini kullanarak integralini tahmin ederek 31 bayt yapabilirim :√(1-x2)1/(1+x2)

4Mean@Sqrt[1-1~RandomReal~#^2]&
Mean[4/(1+1~RandomReal~#^2)]&

9
Hayata, evrene ve her şeye üç çözümün var ve onu mahvetmeye mi karar veriyorsun? Sapınç.
saat


6

CJam, 27 23 22 veya 20 bayt

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

Runner112 sayesinde 2 bayt, Sp3000 sayesinde 1 bayt kaydedildi

STDIN'den yineleme sayısını girdi olarak alır.

Bu, olabildiğince dümdüz. Bunlar dahil olan en önemli adımlar:

  • Girişi okuyun ve bir kez daha Monte Carlo yinelemelerini çalıştırın
  • Her yinelemede, 0'dan 1'e kadar olan iki rasgele yüzen toplam karesini alın ve 1'den küçük olup olmadığını görün.
  • Toplam yinelemelerle kaç kez daha az çarptığımızın oranını elde edin ve PI elde etmek için 4 ile çarpın

Kod genişletme :

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";

Burada çevrimiçi deneyin


Ortalama değeri 1/(1+x^2)Monte Carlo olarak da kabul edilirse, bu 20 baytta yapılabilir:

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

Burada dene


2
Ben de bir CJam cevabı denedim ve puanınızın altında 2 bayt gelmeyi başardım. Ama benim kodum sizinkilere benzer şekilde çıktı, ayrı bir cevap olarak gönderirken kirli hissediyorum. Değişken seçimi ve bu iki optimizasyon hariç her şey aynıydı: 1dmryerine 0'dan 1'e rasgele bir sayı alın ve yerine KmrK/karelerin toplamının iyerine 1'den büyük olup olmadığını kontrol edin 1>( bunun özellikle zekice olduğunu düşündüm) .
Runer112 14.03.2015

@ Runer112 Teşekkürler. ihüner gerçekten temiz! Ve belgelerin eksikliği lanet1dmr
Doktor

5

Python 2, 77 75 bayt

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

Bayt kaydetmek için 4000 örnek kullanır 1e3.


5
Hiçbir ücret ödemeden biraz daha fazla doğruluk elde edebilirsiniz ...*8000;print a/2e3.
Mantık Şövalye

5

Commodore 64 Basic, 45 bayt

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

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

İlk kadranda 1000 puan üretir; her biri için, "x ^ 2 + y ^ 2 <1" in doğruluğunu çalışan bir sayıma ekler, sonra sayımı 250'ye böler pi. (Eksi işaretinin varlığı, C64'te "true" = -1 olduğundandır.)


Ne yapar (1)?
echristopherson

@echristopherson, yanlış okuyorsun. /bölme sembolü değil, SHIFT+Nbir Commodore 64 klavyede yazarak üretilen karakterdir . yani R/(1)kısayol şeklidir RND(1). "mevcut RNG tohumunu kullanarak 0 ile 1 arasında rastgele bir sayı üretin".
Mark

Oh, haklısın! İyi eski PETSCII grafik karakterleri.
echristopherson

5

J, 17 bayt

Ortalama değeri hesaplar 40000fonksiyonunun örnek değerler 4*sqrt(1-sqr(x))aralığındadır [0,1].

Kolayca 0 o.xgeri döner sqrt(1-sqr(x)).

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

4

> <> (Balık) , 114 bayt

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

Şimdi,> <> yerleşik bir rasgele sayı üretecine sahip değildir. Bununla birlikte, işaretçiyi rastgele yönde gönderen bir işlevi vardır. Kodumdaki rasgele sayı üreteci:

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

Temel olarak bir ikili sayı oluşturan rastgele bitleri üretir ve daha sonra bu rasgele ikili sayıyı ondalık sayıya dönüştürür.

Gerisi sadece kare yaklaşımındaki normal noktalardır.

Kullanım: kodu çalıştırdığınızda, örneğin (- python yorumlayıcısında - vt) yığınını örnek sayısıyla önceden doldurduğunuzdan emin olmalısınız.

pi.fish -v 1000

döner

3.164

4

Matlab veya Octave 29 byte (kusur!)

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

(<1 'nin iyi olup olmadığından emin değilim. Okumak için <= 1 olmalı. Ama tam olarak 1 çizme olasılığı ne kadar büyük ...)

Matlab veya Octave 31 bayt

sum(sum(rand(2,4e3).^2)<=1)/1e3

1
Çok güzel bir fikir! İki ek byte ile tasarruf edebilirsiniz mean(sum(rand(2,4e6).^2)<1)*4.
kusurlu

4

Java, 108 bayt

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

Dört bin yineleme, nokta birim daire içinde olduğunda her defasında 0.001 eklenir. Oldukça basit şeyler.

Not: Evet, πtek baytlık bir karaktere geçerek dört bayt tutabileceğimi biliyorum . Bu şekilde seviyorum.


neden 9999 yineleme değil?
Doktor,

1
@Optimizer Toplamı kısaltır. 9999 yineleme için, her seferinde daha kesin bir rakam eklemeliyim ki bu rakam bana mal oluyor.
Geobits

1
Numaralar için "4e5" ve "1e-5" tuşlarını kullanarak başka bir bayttan tasarruf edebilir ve hassasiyeti artırabilirsiniz.
Vilmantas Baranauskas

@VilmantasBaranauskas Teşekkürler! Bunu hep unutmuşum :) Bunun yerine 4e9 ve 1e-9 kullanmak cazip geliyor, ancak bu oldukça uzun sürüyor ...
Geobits

Protip: Golf yaparken, aslında baytları azaltmalısınız, yapay olarak onları arttırmamalısınız
Yok

3

Javascript: 62 Bayt

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

Önceki (şimdi silinmiş) javascript yanıtını kullandım ve 5 baytı traş oldum.


Sen olabilir cfern cevabı bağlantı düzgün vermek krediye.
Jonathan Frech

Cevabınız, I / O’ya izin verilmeyen bir pasaj gibi görünüyor . Lütfen yayınınızı düzeltin veya silin.
Jonathan Frech

Üzgünüm, yeniyim Bağlantıyı şimdi silinmiş görünen önceki çözüme nasıl koyacağımı bilmiyordum. Metin parçacığı ile ilgili olarak: Tamamen katılıyorum, ancak bu, bu nedenle geçersiz olduğunu düşündüğüm önceki javascript çözümünün koduydu. Benimkini program olarak değiştirdim.
Guzman Tierno

Evet; önceki cevap geçersiz olduğu için silindi - cevabını silmeyi tavsiye etmeden önce cevabını gördüm. Geçerli bir cevap göndermek için + 1; PPCG'ye hoş geldiniz!
Jonathan Frech

2

GolfScript (34 karakter)

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

Çevrimiçi demo

Bu, sabit nokta kullanır çünkü GS'de kayan nokta yoktur. Sabit nokta kullanımını hafifçe kötüye kullanır, bu nedenle yineleme sayısını değiştirmek istiyorsanız bunun iki katı bir güç olduğundan emin olun.

Kullanılan belirli Monte Carlo yöntemi için xnor kredi .


2

Python 2, 90 85 81 bayt

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

3.14120037157örneğin döndürür . Örnek sayısı 4782969 (9 ^ 7). 9 ^ 9 ile daha iyi bir pi alabilirsiniz ancak sabırlı olmanız gerekir.


Sen değiştirerek 3 kaydedebilirsiniz range(9**7)ile [0]*9**7kullanmak vermediği için, ya da bir şey i. Ve liste hafıza sorunlarıyla karşılaşmak için çok uzun değil.
Sp3000,

Teşekkürler. Kurtulmak istedim range()ama bu numarayı tamamen unutmuştum.
Mantık Şövalye

[0]9**7Geçerli bir sözdizimi olmadığını hissediyorum .
15'de

Haklısın. Kaybolan asteri yeniden ekledim (masamın altındaydı).
Mantık Şövalye

2

Ruby, 39 bayt

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

Vurgulama noktalarından biri, 8e5bunun, aynı program bayt sayısında ~ 8e9 örneklere kadar genişletilebilir olmasını sağlayan notasyonu kullanabilmesidir .



1

Scala, 87 77 66 bayt

def s=math.pow(math.random,2);Seq.fill(1000)(s+s).count(_<1)/250d

Eğer değiştirirseniz 1000ile 8000ve 250dile 2e4bir byte tasarrufu hem siz ve 8. kat örneklerin sayısını artırmak
Dave Swartz

1

Saf Bash, 65 bayt

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

Örnek sayısını vermek için 4 ile çarpılan tek bir komut satırı parametresi alır. Bash aritmetiği sadece tamsayıdır, bu yüzden rasyonel bir çıktı verilir. Bu bc -l, son bölüm için boruya bağlanabilir :

$ ./montepi.sh 10000
31477/10000
$ ./montepi.sh 10000|bc -l
3.13410000000000000000
$ 

1

Joe , 20 19 bayt

Not: Bu cevap rakip değildir, çünkü rastgele eklenmiş olan 0.1.2 sürümü bu meydan okumadan sonra piyasaya sürülmüştür.

Adlandırılmış işlev F:

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

Adsız işlev:

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

Her ikisi de örnek sayımı argüman olarak alır ve sonucu döndürür. Nasıl çalışıyorlar?

%$,(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

Örnek çalışır:

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

1

dc, 59 karakter (boşluk yoksayıldı)

[? 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

Bunu Plan 9 ve OpenBSD'de test ettim, bu yüzden Linux'ta (GNU?) Çalışacağını hayal ediyorum dc.

Satıra göre açıklama:

  1. Kodu [iki float oku ve karesine; [ i1 onların karelerinin toplamından büyükse] register'ı register olarak çalıştırın u.
  2. Kodu kayıt defterinde [ x1 kayıt arttırma ] olarak saklar i.
  3. Kayıt kodunda [register register u, register register m, ve register zregisterdan mbüyükse n] register'ı saklar z.
  4. Ölçeği 5 ondalık noktaya ayarlayın.

  5. İlk giriş satırından örneklenecek nokta sayısını okuyun.
  6. Kayıt işlemini yürütün z.
  7. Kayıt defterini x(isabet sayısı) kayıt defterine n(puan sayısı) bölün, sonucu 4 ile çarpın ve yazdırın.
  8. Çıkın.

Ancak aldattım:

Programın 0 ile 1 arasında bir rasgele yüzer kaynağı olması gerekiyor.

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

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

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

Kullanımı:

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

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

Test sürüşü:

% runpi 10000
3.14840

Şimdi daha az aldatma ile (100 bayt)

Biri basit bir prng içerebileceğime işaret etti.
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

Ungolfed

[
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

Test sürüşü:

$ echo 10000 | dc pigolf.dc
3.13640

1

Pyth, 19

c*4sm<sm^OQ2 2*QQQQ

İstenilen yineleme sayısını girdi olarak verin.

gösteri

Pyth "Rastgele yüzer sayı" işlevine sahip olmadığından doğaçlama yapmam gerekti. Program girişten daha az iki rasgele pozitif tamsayı seçer, kareler, toplamlar ve giriş kareleri ile karşılaştırılır. Bu, girişe eşit sayıda gerçekleştirildi, ardından sonuç 4 ile çarpıldı ve giriş ile bölündü.

İlgili haberlerde, kısa süre içinde Pyth'e rastgele bir kayan nokta sayı işlemi ekleyeceğim. Ancak bu program bu özelliği kullanmaz.


"Sonuç, kayan nokta, sabit nokta veya rasyonel sayı olarak döndürülebilir veya yazdırılabilir." liberal olarak, daha sonra elde edilen fraksiyonun pay ve paydasının basılması yeterli olacaktır. Bu durumda:

Pyth, 18

*4sm<sm^OQ2 2*QQQQ

Bu aynı programdır, kayan nokta bölme işlemi ( c) kaldırılmıştır.


1

Julia, 37 bayt

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

Numune sayısı 65536'dır (= 4 ^ 8).

Daha uzun bir değişken: stek değişken olarak örnek sayısı içeren bir işlev :

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

1

C, 130 bayt

#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);}

Ungolfed:

#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);
}

Tabii ki, muhtemelen hala boşluk olmadan sürümü yayınlamanız gerekir (geçerli sürümü "ungolfed / boşluklu" başlığıyla saklayın)
Destructible Lemon

@ YıkılabilirWatermelon yapılır!
Karl Napf

Çözüm, daha önce yeni bir satır olmadan GCC'de çalışmıyor f(). Hangi derleyiciyi kullandın? Bakınız tio.run/##Pc49C4JAHIDx3U9xGMG9ZdYgwWkgtNbQ1BZ6L/UHO8M07hA/…
eush77


1

Aslında , 14 bayt (rekabet etmeyen)

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

Çevrimiçi deneyin!

Bu çözüm rekabet edici değil çünkü dil mücadeleye son veriyor. Numune sayısı girdi olarak verilmiştir (kodlanmış kod yerine).

Açıklama:

`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

2
Neden aşağı oy?
Yıkılabilir Limon

1

Raket 63 bayt

@Matt tarafından R dilindeki cevap yöntemini kullanarak:

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

Ungolfed:

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

Test yapmak:

(f 10000)

Çıktı (kesir):

3 31491308966059784/243801776017028125

Ondalık olarak:

(exact->inexact(f 10000))

3.13583200307849

1

Fortran (GFortran) , 84 83 bayt

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

Çevrimiçi deneyin!

Bu kod çok kötü yazdı. Eğer gfortran değişkeni Abaşka bir değerle başlatmaya karar verirse, o zaman 0 (derlemelerin% 50'sini oluşturur), veA 0 olarak ilklendirilirse, verilen tohum için her zaman aynı rastgele diziyi oluşturur. Ardından, Pi için aynı değer her zaman yazdırılır.

Bu çok daha iyi bir program:

Fortran (GFortran) , 100 99 bayt

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

Çevrimiçi deneyin!

(Her sürümde bir bayt kaydedildi; teşekkürler Penguino).


1
Her sürümde 'DO I = 1,1E3' 'ü' DO I = 1,4E3 'değiştirerek,' A = A + 1 '' i 'A = A + 1E-3' değiştirerek 'değiştirerek bir bayt kaydedebilirsiniz. YAZDIR *, A / 250 'den' YAZDIR *, A '
Penguino

Evet, eminsin! Öneriniz için teşekkürler!
rafa11111

1

Japt , 26 veya 18 bayt

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

Çevrimiçi deneyin!

Optimizer’ın cevabına benzer , sadece Japt öğrenmeye çalışıyorum.
Örtük girdi olarak çalıştırılacak yineleme sayısını alır 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.

Eğer 1/(1+x^2)(yerine iki ayrı randoms) izin verilir, o zaman aynı mantıkla 18 bayt elde edebilirsiniz.

o r_Ä/(1+Mr pÃ*4/U

1
MhHipotenüsü kendiniz yapmak yerine hesaplayarak birkaç bayttan tasarruf edebilirsiniz ;-) Ayrıca, xbir dizinin toplamını almak yerine, ekleme o x@MhMr Mr)<1Ã*4/U
yaparak

@ETHproductions Neat, böyle kullanabileceğini bilmiyordum Mh, teşekkürler! İki rastgele cevabınız, neredeyse bir rasgele cevabım kadar kısa, bu oldukça havalı. xAklımda tutacağım , golf oynamaya çalışırken azaltmayı çok kullanmaya meyilliyim, bu yüzden bu çok kullanışlı olacak.
Nit

1

F #, 149 bayt

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

Çevrimiçi deneyin!

Yapabildiğim kadarıyla, F # 'da bu tür bir koşu toplamı yapmak, bir sayı dizisi oluşturmak ve Seq.sumByyöntemi bir for..to..doblok kullanmaktan daha kısa sürer .

Bu kod, 1'den 1'e kadar olan kayan noktalardan oluşan bir sayı koleksiyonu oluşturur, koleksiyondaki öğe sayısı siçin işlevi yerine getirir fun x->...ve sonucu toplar. sKoleksiyonda elementler var , bu yüzden rastgele test skez yapıldı. Koleksiyondaki gerçek sayılar yoksayılır ( fun x->, ancak xkullanılmaz).

Ayrıca, uygulamanın önce diziyi oluşturup doldurması ve ardından üzerinde yineleme yapması gerektiği anlamına gelir. Bu yüzden muhtemelen bir for..to..dodöngü iki kat daha yavaş . Dizi oluşturma işleminde bellek kullanımı O (f ** k) bölgesindedir!

Gerçek testin kendisi için, bir if then elseifade kullanmak yerine, yaptığı şeyi ( q()+q()|>Math.Sqrt) mesafeyi hesaplar ve aşağı yuvarlar Math.Floor. Mesafe çemberin içindeyse, 0'a yuvarlanır. Mesafe çemberin dışındaysa 1'e yuvarlanır. Seq.sumByYöntem daha sonra bu sonuçları toplar.

O zaman Seq.sumBytoplamın çember içindeki noktalar değil, dışındaki noktalar olduğuna dikkat edin. Böylece sonuç s(bizim örneklem boyutumuz) alır ve toplamı ondan çıkarır.

Ayrıca parametre olarak örneklem büyüklüğünün alınmasının, değerin zor kodlanmasından daha kısa olduğu görülmektedir. Bu yüzden biraz hile yapıyorum ...


1

Haskell, 116 114 110 96 bayt

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

import System.Random; r=randoms(mkStdGen 2)Bununla uğraşmak çok fazla değerli bayt alacağından, bazılarının neredeyse şifreleme açısından güçlü olduğunu söyleyen doğrusal eşlenik üretici ile sonsuz rasgele sayılar listesi x↦x*9+1 mod 8^9hazırlarım : ki bu Hull-Dobell Teoremi'nin tüm dönemine sahiptir 8^9.

gverim 4rasgele sayı noktası olarak rasgele sayı çiftleri için daire içinde ise, [0..8^9-1]bu ortadan kaldırır formüldeki bir çarpma kullanıldığı için.

Kullanımı:

> p 100000
3.14208

Çevrimiçi deneyin!


1

Perl 5, 34 bayt

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

Numune sayısı stdin'den alınmıştır. Gerektirir -p.

Çünkü işe yarıyor:

Çevrimiçi deneyin!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.