Pi의 몬테카를로 추정기


25

행복한 파이의 날 여러분! 전혀 이유없이, 나는 Pi의 Monte Carlo Estimator를 가능한 한 짧게 구성하려고합니다. 트윗에 맞는 것을 만들 수 있습니까?

명확히하기 위해, 내가 염두에두고있는 것은 단위 사각형에서 임의의 점을 그리고 단위 원에 속하는 비율을 계산하는 일반적인 접근 방식입니다. 샘플 수는 하드 코딩되거나 코딩되지 않을 수 있습니다. 하드 코딩하는 경우 1000 개 이상의 샘플을 사용해야합니다. 결과는 부동 소수점, 고정 소수점 또는 유리수로 반환되거나 인쇄 될 수 있습니다.

삼각 함수 또는 Pi 상수가 없어도 Monte Carlo 방식이어야합니다.

이것은 코드 골프이므로 가장 짧은 제출 (바이트)이 이깁니다.


2
삼각 함수가 허용됩니까? 나는 당신이 그들을 명시 적으로 금지하는 것이 좋습니다.
Level River St

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

@ JanDvorak 어떻게 작동합니까? 은하지 않습니다 map당신의 배열 줄 true과를 false?
Martin Ender

@ MartinBüttner 아 죄송합니다. .filter{...}.size그래도 작동해야합니다.
John Dvorak

@JanDvorak 참으로. 정말 깔끔합니다 :)
Martin Ender

답변:


17

80386 기계 코드, 40 38 바이트

코드의 16 진 덤프 :

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

이 코드를 얻는 방법 (조립 언어에서) :

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

이것은 MS fastcall호출 규칙을 사용하는 함수 입니다 (반복 횟수는 register에 전달됨 ecx). st레지스터에 결과를 반환합니다 .

이 코드에 대한 재미있는 것 :

  • rdrand -난수를 생성하기 위해 단 3 바이트!
  • 최종 나누기까지 (부호없는) 정수 산술을 사용합니다.
  • 제곱 거리 ( D)와 제곱 반경 ( 2^32)을 자동으로 비교 합니다. 캐리 플래그에 결과가 포함됩니다.
  • 카운트에 4를 곱하기 위해 샘플을 4 단계로 계산합니다.

코멘트는 "x ^ 2 % 2 ^ 32 계산"
Cole Johnson

@ColeJohnson 아니요-난수가 있습니다 eax. 이 mul명령은 그 자체로 다중화하여 높은 부분을 차지합니다 edx. 낮은 부분 eax은 폐기됩니다.
아나톨리 그

11

Matlab / Octave, 27 바이트

Matlab / Octave 답변이 이미 있다는 것을 알고 있지만 내 접근법을 시도했습니다. 나는 4/(1+x^2)0과 1 사이 의 적분 이 pi 라는 사실을 사용했습니다 .

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

다른 알고리즘은 항상 좋습니다! 또한 더 효율적입니다!
아나톨리 그

7

R, 40 (또는 다른 방법을 사용하는 28 또는 24)

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

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

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

파이썬 2, 56

numpy가 허용되지만 Matlab / Octave와 매우 유사한 또 다른 Python입니다.

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

6

Mathematica, 42 40 39 바이트 (또는 31/29?)

42 바이트에 세 가지 솔루션이 있습니다.

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

그것들은 모두 샘플 수를 취하고 n합리적 근사 π를 반환하는 명명되지 않은 함수입니다 . 먼저 모두 n양의 사분면에서 단위 제곱의 점을 생성 합니다. 그런 다음 단위 원 안에있는 샘플 수를 결정한 다음 샘플 수로 나누고을 곱합니다 4. 유일한 차이점은 단위 원 내부의 샘플 수를 결정하는 방법에 있습니다.

  • 첫 번째 Count조건은 Norm[p] < 1.
  • 두 번째는 각 점의 규범을 빼고 1반올림합니다. 이에 단위 원 안에 숫자를 회전 1과에 그 외부 0. 그 후 나는 그들과 모두를 요약합니다 Tr.
  • 세 번째는 본질적으로 동일하지만 from을 빼 1.5므로 Round대신 사용할 수 있습니다 Ceiling.

이 글 쓰는 동안 Aaaaaand 는 실제로 빼고 2사용 하면 더 짧은 해결책이 있다는 것을 알게되었습니다 Floor.

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

또는 유니 코드 바닥 또는 천장 연산자를 사용하여 다른 바이트를 저장하십시오.

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

3 개의 반올림 기반 솔루션은 동일한 바이트에 대해. Mean대신 Tr및을 사용하여 /#다시 작성할 수 있습니다 .


다른 몬테카를로 기반의 접근 방식이 좋으면 (특히 Peter가 선택한 방법) 정수를 사용하여 정수 또는 29를 추정하여 31 바이트를 수행 할 수 있습니다. 이번에는 부동 소수점 숫자로 지정됩니다.√(1-x2)1/(1+x2)

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

9
당신은 인생, 우주 및 모든 것에 대한 세 가지 해결책을 가지고 있으며 그것을 망치기로 결정 했습니까? 이교.
seequ


6

CJam, 27 23 22 또는 20 바이트

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

Runner112 덕분에 2 바이트 절약, Sp3000 덕분에 1 바이트 절약

STDIN의 반복 횟수를 입력으로 사용합니다.

이것은 가능한 한 빨리 진행됩니다. 관련된 주요 단계는 다음과 같습니다.

  • 입력을 읽고 여러 번 Monte Carlo 반복을 실행하십시오.
  • 각 반복에서 0에서 1까지의 두 개의 임의 부동 소수점의 제곱의 합을 얻고 1보다 작은 지 확인하십시오.
  • PI를 얻기 위해 총 반복으로 1보다 적은 횟수의 비율을 구하고 4를 곱하십시오.

코드 확장 :

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

여기에서 온라인으로 사용해보십시오


평균 값이 1/(1+x^2)Monte Carlo로 간주되면 20 바이트로 수행 할 수 있습니다.

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

여기 사용해보십시오


2
CJam 답변도 시도했지만 점수가 2 바이트로 떨어졌습니다. 그러나 내 코드가 귀하의 코드와 너무 비슷하게 나왔으므로 별도의 답변으로 게시하는 것이 더럽습니다. 변수 선택 과이 두 가지 최적화를 제외하고는 모두 동일했습니다. 1dmr대신 0에서 1 사이의 임의의 숫자를 얻고 KmrK/제곱의 합이 i대신 1보다 큰지 확인하십시오 1>(특히이 영리하다고 생각했습니다) .
Runer112

@ Runer112 감사합니다. i트릭은 정말 깔끔하네요! 다음에 대한 문서가 부족합니다.1dmr
Optimizer

5

파이썬 2, 77 75 바이트

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

4000 개의 샘플을 사용하여 바이트를 절약합니다 1e3.


5
을 (를) 사용하면 무료로 조금 더 정확하게 얻을 수 ...*8000;print a/2e3있습니다.
논리 기사

5

코모도어 64 베이직, 45 바이트

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

PETSCII 대체 : = SHIFT+E, /= SHIFT+N, =SHIFT+O

1 사분면에서 1000 점을 생성합니다. 각각에 대해 "x ^ 2 + y ^ 2 <1"의 진위를 누적 횟수에 더한 다음 개수를 250으로 나누어 얻습니다 pi. 빼기 부호가 있으면 C64에서 "true"= -1이기 때문입니다.


무엇을 (1)합니까?
echristopherson

@ echristopherson, 당신은 그것을 잘못 읽고 있습니다. /나누기 기호가 아니라 SHIFT+NCommodore 64 키보드 로 입력하여 생성되는 문자 입니다. 즉, R/(1)바로 가기 양식입니다 RND(1). "현재 RNG 시드를 사용하여 0과 1 사이의 난수를 생성합니다."
Mark

아, 맞아! 오래된 PETSCII 그래픽 캐릭터.
echristopherson

5

J, 17 바이트

범위 내 40000에서 함수 샘플 값의 평균값을 계산합니다 .4*sqrt(1-sqr(x))[0,1]

0 o.x반환합니다 sqrt(1-sqr(x)).

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

4

> <> (물고기) , 114 바이트

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

이제> <>에는 내장 난수 생성기가 없습니다. 그러나 포인터를 임의의 방향으로 보내는 기능이 있습니다. 내 코드의 난수 생성기 :

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

기본적으로 이진수를 구성하는 임의의 비트를 생성 한 다음이 임의의 이진수를 10 진수로 변환합니다.

나머지는 정사각형 접근 방식의 일반적인 포인트입니다.

사용법 : 코드를 실행할 때 샘플 수로 스택 (python 인터프리터에서 -v)을 미리 채워야합니다 (예 :

pi.fish -v 1000

보고

3.164

4

Matlab 또는 Octave 29 바이트 (플레어 덕분에)

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

(<1이 정상인지 확실하지 않습니다. <= 1이어야 함을 읽습니다. 그러나 정확히 1을 그릴 확률은 얼마나 큽니까 ...)

Matlab 또는 Octave 31 바이트

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

1
아주 좋은 생각입니다! 을 사용하여 두 개의 추가 바이트를 저장할 수 mean(sum(rand(2,4e6).^2)<1)*4있습니다.
flawr

4

자바, 108 바이트

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

점이 단위 원 안에있을 때마다 0.001을 더하는 4 천회 반복. 아주 기본적인 것들.

참고 : 예, 1 π바이트 문자 로 변경 하여 4 바이트를 흘릴 수 있다는 것을 알고 있습니다 . 나는 이런 식으로 그것을 좋아한다.


왜 9999 회 반복하지 않습니까?
Optimizer

1
@Optimizer 합계를 짧게 만듭니다. 9999 반복의 경우 매번 더 정확한 숫자를 추가해야하므로 숫자가 필요합니다.
Geobits

1
숫자에 "4e5"및 "1e-5"를 사용하여 다른 바이트를 절약하고 정밀도를 향상시킬 수 있습니다.
Vilmantas Baranauskas

트윗 담아 가기 나는 항상 그것을 잊어 버린다 :) 대신 4e9와 1e-9를 사용하고 싶은 유혹이 있지만, 꽤
오랜

팁 : 골프를 칠 때는 실제로 바이트를 줄여야하며 인위적으로 늘리지 않아야합니다.
Destructible Lemon

3

자바 스크립트 : 62 바이트

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

이전 (현재 삭제 된) 자바 스크립트 답변을 사용하고 5 바이트를 면도했습니다.


크레딧을 올바르게 제공하기 위해 cfern의 답변연결할 수 있습니다.
Jonathan Frech

귀하의 답변은 I / O허용되지 않는 스 니펫 인 것 같습니다 . 게시물을 수정하거나 삭제하십시오.
Jonathan Frech

죄송합니다. 새로운 솔루션으로, 이전 솔루션에 대한 링크를 삭제하는 방법을 몰랐습니다. 스 니펫과 관련하여 : 나는 완전히 동의하지만, 그것은 이전 자바 스크립트 솔루션의 코드이기도했기 때문에 그 이유도 올바르지 않다고 생각합니다. 나는 프로그램으로 내 것을 수정했다.
Guzman Tierno

예; 이전 답변이 잘못되어 삭제되었습니다. 삭제를 추천하기 전에 답변을 보았습니다. 유효한 답변을 제출하면 +1; PPCG에 오신 것을 환영합니다!
Jonathan Frech

2

GolfScript (34 자)

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

온라인 데모

GS에는 실제로 부동 소수점이 없기 때문에 고정 소수점을 사용합니다. 고정 소수점 사용을 약간 남용하므로 반복 횟수를 변경하려면 10의 거듭 제곱 인 것을 확인하십시오.

신용하는 배타적 부정 사용 된 특정 몬테 카를로 방법에 대해.


2

파이썬 2, 90 85 81 바이트

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

3.14120037157예를 들어 반환 합니다. 샘플 수는 4782969 (9 ^ 7)입니다. 9 ^ 9로 더 나은 파이를 얻을 수 있지만 인내심을 가져야합니다.


당신은 대체하여 3을 절약 할 수 있습니다 range(9**7)와 함께 [0]*9**7사용하지 않기 때문에, 또는 뭔가 i. 그리고 목록이 너무 길어서 메모리 문제가 발생하지 않습니다.
Sp3000

감사. 나는 제거하고 싶었지만 range()그 트릭을 완전히 잊어 버렸습니다.
논리 기사

나는 느낌이 [0]9**7유효한 구문이 아닙니다.
seequ

네 말이 맞아 나는 잃어버린 별표를 다시 부착했습니다 (제 책상 아래있었습니다).
논리 기사

2

루비, 39 바이트

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

하이라이트 중 하나는이 8e5표기법 을 사용 하여 동일한 프로그램 바이트 수에서 ~ 8e9 샘플까지 확장 할 수 있다는 것입니다.



1

Scala, 87 77 66 bytes

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

If you replace 1000 with 8000 and 250d with 2e4 you both save a byte and increase the number of samples by a factor of 8.
Dave Swartz

1

Pure Bash, 65 bytes

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

Takes a single command-line parameter which is multiplied by 4 to give the number of samples. Bash arithmetic is integer-only, so a rational is output. This may be piped to bc -l for the final division:

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

1

, 20 19 bytes

참고 :이 도전 이후에 임의성을 추가 한 0.1.2 버전이 출시되었으므로이 답변은 경쟁이 아닙니다.

명명 된 기능 F :

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

이름없는 기능 :

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

둘 다 샘플 수를 인수로 사용하여 결과를 반환합니다. 그들은 어떻게 작동합니까?

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

예제 실행 :

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

1

dc, 59 자 (공백은 무시 됨)

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

나는 이것을 Plan 9와 OpenBSD에서 테스트 했으므로 Linux (GNU?)에서 작동한다고 상상합니다 dc.

라인 별 설명 :

  1. 코드를 저장하고 두 개의 수레를 읽습니다. register에서 i1이 제곱의 합보다 큰 경우 register를 실행하십시오 u.
  2. 레지스터의 코드를 [ x1 씩 증가 레지스터 ]에 저장i.
  3. [execute register u, incremental register ]에 코드를 저장 m한 다음 register에서 register z가 register m보다 큰 경우 register 를 실행 합니다. nz
  4. 스케일을 소수점 5 자리로 설정하십시오.

  5. 첫 번째 입력 라인에서 샘플링 할 포인트 수를 읽습니다.
  6. 레지스터 실행 z.
  7. 레지스터 x(적중 횟수)를 레지스터로 나눕니다.n (점 수)로 나누고 결과에 4를 곱한 후 인쇄하십시오.
  8. 떠나다.

그러나 나는 속였다.

이 프로그램에는 0과 1 사이의 임의의 부동 소수점 공급이 필요합니다.

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

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

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

용법:

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

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

시운전 :

% runpi 10000
3.14840

이제 부정 행위가 줄어 듭니다 (100 바이트)

누군가 내가 간단한 prng을 포함시킬 수 있다고 지적했다.
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

언 골프

[
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

시운전 :

$ echo 10000 | dc pigolf.dc
3.13640

1

피 이스, 19

c*4sm<sm^OQ2 2*QQQQ

원하는 반복 횟수를 입력하십시오.

데모

Pyth에는 "Random floating number"기능이 없으므로 즉흥적으로해야했습니다. 프로그램은 입력, 제곱, 합보다 작고 입력 제곱과 비교되는 두 개의 임의의 양의 정수를 선택합니다. 이 작업은 입력과 동일한 횟수만큼 수행 된 다음 결과에 4를 곱한 후 입력으로 나눕니다.

관련 뉴스에서는 곧 Pyth에 임의의 부동 소수점 숫자 연산을 추가 할 것입니다. 그러나이 프로그램은 해당 기능을 사용하지 않습니다.


"결과는 부동 소수점, 고정 소수점 또는 유리수로 반환되거나 인쇄 될 수 있습니다." 자유롭게, 그런 다음 결과 분수의 분자와 분모를 인쇄하는 것으로 충분합니다. 이 경우 :

피스, 18

*4sm<sm^OQ2 2*QQQQ

부동 소수점 나누기 연산 ( c)이 제거 된 동일한 프로그램 입니다.


1

줄리아, 37 바이트

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

샘플 수는 65536 (= 4 ^ 8)입니다.

엄밀히 더 긴 변형 : s유일한 인수로 샘플 수를 가진 함수 :

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

1

C, 130 bytes

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

물론, 당신은 여전히 ​​공백없이 버전을 게시해야 할 것입니다 (현재 공백을 "공백 없음 / 공백"등으로 유지하십시오)
Destructible Lemon

@DestructibleWatermelon 완료!
Karl Napf

솔루션은 개행없이 GCC에서 작동하지 않습니다 f(). 어떤 컴파일러를 사용 했습니까? 참조 tio.run/##Pc49C4JAHIDx3U9xGMG9ZdYgwWkgtNbQ1BZ6L/UHO8M07hA/...
eush77


1

실제로 14 바이트 (비경쟁)

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

온라인으로 사용해보십시오!

언어가 도전 과제를 게시하기 때문에이 솔루션은 경쟁이 아닙니다. 샘플 수는 하드 코딩이 아닌 입력으로 제공됩니다.

설명:

`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
왜 공감해야합니까?
Destructible Lemon

1

라켓 63 바이트

@Matt의 R 언어 답변 방법 사용 :

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

언 골프 드 :

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

테스트 :

(f 10000)

출력 (분수) :

3 31491308966059784/243801776017028125

십진수로 :

(exact->inexact(f 10000))

3.13583200307849

1

Fortran (GFortran), 84 83 bytes

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

Try it online!

This code is very bad wrote. It will fail if gfortran decide to initialize variable A with other value then 0 (which occurs 50% of the compilations, approximately) and, if A is initialized as 0, it will always generate the same random sequence for the given seed. Then, the same value for Pi is printed always.

This is a much better program:

Fortran (GFortran), 100 99 bytes

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

Try it online!

(One byte saved in each version; thanks Penguino).


1
In each version you can save a byte by changing 'DO I=1,1E3' to 'DO I=1,4E3', changing 'A=A+1' to 'A=A+1E-3', and changing 'PRINT*,A/250' to 'PRINT*,A'
Penguino

Yes, you are sure! Thank for the suggestion!
rafa11111

1

Japt, 26 or 18 bytes

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

Try it online!

Analogous to Optimizer's answer, mainly just trying to learn Japt.
Takes the number of iterations to run for as the implicit input 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.

If 1/(1+x^2) is allowed (instead of two separate randoms), then we can achieve 18 bytes with the same logic.

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

1
You can save a few bytes by letting Mh calculate the hypotenuse rather than doing it yourself ;-) Also, you can use x to take the sum of an array, rather than reducing by addition: o x@MhMr Mr)<1Ã*4/U
ETHproductions

@ETHproductions Neat, I didn't know you can use Mh like that, thanks! Your two-random answer is nearly as short as my answer with only one random, that's pretty cool. I'll keep x in mind, I tend to use reduction a lot when trying to golf stuff, so this will come in very handy.
Nit

1

F#, 149 bytes

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

Try it online!

As far as I can make out, to do this kind of running total in F# it's shorter to create an array of numbers and use the Seq.sumBy method than use a for..to..do block.

What this code does it that it creates a collection of floating-point numbers from 1 to s, performs the function fun x->... for the number of elements in the collection, and sums the result. There are s elements in the collection, so the random test is done s times. The actual numbers in the collection are ignored (fun x->, but x is not used).

It also means that the application has to first create and fill the array, and then iterate over it. So it's probably twice as slow as a for..to..do loop. And with the array creation memory usage is in the region of O(f**k)!

For the actual test itself, instead of using an if then else statement what it does is it calculates the distance (q()+q()|>Math.Sqrt) and rounds it down with Math.Floor. If the distance is within the circle, it'll be rounded down to 0. If the distance is outside the circle it'll be rounded down to 1. The Seq.sumBy method will then total these results.

Note then that what Seq.sumBy has totalled is not the points inside the circle, but the points outside it. So for the result it takes s (our sample size) and subtracts the total from it.

It also appears that taking a sample size as a parameter is shorter than hard-coding the value. So I am cheating a little bit...


1

Haskell, 116 114 110 96 bytes

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

Because dealing with import System.Random; r=randoms(mkStdGen 2) would take too many precious bytes, I generate an infinite list of random numbers with the linear congruential generator that some say is almost cryptographically strong: x↦x*9+1 mod 8^9, which by the Hull-Dobell Theorem has the full period of 8^9.

g yields 4 if the random number point is inside the circle for pairs of random numbers in [0..8^9-1] because this eliminates a multiplication in the formula used.

Usage:

> p 100000
3.14208

Try it online!


1

Perl 5, 34 bytes

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

The number of samples is taken from stdin. Requires -p.

Works because:

Try it online!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.