Piのモンテカルロ推定量


25

みんなハッピーパイデー!理由もなく、可能な限り短いPiのモンテカルロ推定量を構築しようとしています。ツイートに収まるものを構築できますか?

明確にするために、私が念頭に置いているのは、単位正方形からランダムな点を描き、単位円内に入る比率を計算する典型的なアプローチです。サンプルの数は、ハードコーディングすることも、しないこともできます。それらをハードコーディングする場合、少なくとも1000サンプルを使用する必要があります。結果は、浮動小数点、固定小数点、または有理数として返されるか出力される場合があります。

トリガー関数やPi定数は、モンテカルロアプローチではありません。

これはコードゴルフであるため、最短の提出(バイト単位)が優先されます。


2
トリガー関数は許可されていますか?明示的に禁止することをお勧めします。
レベルリバーセント

((0..4e9).map{rand**2+rand**2<1}.to_s.sub(/./,"$1.")
ジョンドヴォルザーク

@JanDvorakそれはどのように機能するはずですか?ていないmapあなたの配列を与えるtruefalse
マーティンエンダー

@MartinBüttnerああ、おっと、すみません。.filter{...}.sizeただし、動作するはずです。
ジョン・ドヴォルザーク

@JanDvorak確かに。それは本当にすてきです:)
マーティンエンダー

回答:


17

80386マシンコード、40 38バイト

コードの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

(アセンブリ言語から)このコードを取得する方法:

    // 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のステップでサンプルをカウントします。

コメントは「Calculate x ^ 2%2 ^ 32」と読みます
コールジョンソン

@ColeJohnsonません-乱数ですeaxmul自身とプットによるコマンド倍数にそれを高い部分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))

Python 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バイトの3つのソリューションがあります。

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ます。
  • 2番目のものは、各点のノルムを減算してから1切り上げます。これにより、単位円内の数値はに、1外部の数値はになります0。その後、それらをすべてまとめTrます。
  • 3番目のものは基本的に同じですが、fromを減算する1.5ため、のRound代わりに使用できますCeiling

Aaaaaand ながらこれまでに書いて、私がちょうどから引く場合短いソリューションは、確かにそこにあることを私に発生し2、その後、使用しますFloor

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

または、Unicodeのフロア演算子または天井演算子を使用して別のバイトを保存します。

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

また、3つの丸めベースのソリューションは、同じバイトに対してのMean代わりにTr、なしで記述できることに注意してください/#


他のモンテカルロベースのアプローチがうまくいけば(具体的にはPeterが選択した方法)、の積分を使用して31バイトを推定できます。√(1-x2)1/(1+x2)

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

9
人生、宇宙、すべてに対する3つの解決策があり、それを台無しにすることに決めましたか?異端。
seequ


6

CJam、27 23 22または20バイト

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

Runner112のおかげで2バイト節約、Sp3000のおかげで1バイト節約

STDINからの反復カウントを入力として受け取ります。

これは簡単です。これらは主要なステップです:

  • 入力を読み取り、モンテカルロ反復を何度も実行します
  • 各反復で、0から1までの2つのランダムなフロートの平方和を取得し、1より小さいかどうかを確認します
  • 合計反復回数で1未満になった回数の比率を取得し、4で乗算してPIを取得します

コード拡張

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)もモンテカルロと見なされる場合、これは20バイトで実行できます。

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

ここで試してみてください


2
CJamの回答も試してみましたが、なんとかあなたのスコアの下に2バイト入りました。しかし、私のコードはあなたのものと同じように出てきたので、別の答えとして投稿するのは汚い気がします。変数の選択とこれら2つの最適化以外はすべて同じでした:の1dmr代わりに0から1の乱数を取得しKmrK/、平方和がのi代わりに1より大きいかどうかを確認します1>(これは特に賢いと思いました) 。
Runer112

@ Runer112ありがとう。iトリックは本当にきれいです!そして、次のドキュメントの欠如を気にします1dmr
オプティマイザー

5

Python 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

Commodore 64 Basic、45バイト

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

PETSCII置換:= SHIFT+E/= SHIFT+N=SHIFT+O

最初の象限に1000ポイントを生成します。それぞれについて、「x ^ 2 + y ^ 2 <1」の真理を実行中のカウントに追加し、カウントを250で割ってを取得しpiます。(マイナス記号の存在は、C64では「true」= -1であるためです。)


何を(1)するの?
-echristopherson

@echristopherson、あなたはそれを誤解しています。 /は分割記号ではなく、SHIFT+NCommodore 64キーボードで入力することで生成される文字です。 R/(1)は、のショートカット形式ですRND(1)。「現在のRNGシードを使用して0〜1の乱数を生成します」。
マーク

ああ、あなたは正しい!古き良き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*^__
 __________
___________ _
_____ ____ _______
_____ ____~ ______

基本的に、2進数を構成するランダムビットを生成し、その2進数を10進数に変換します。

残りは、スクエアアプローチの通常のポイントです。

使用法:コードを実行するときは、サンプルの数でスタック(Pythonインタープリターの-v)を事前に設定する必要があります。たとえば、

pi.fish -v 1000

返す

3.164

4

MatlabまたはOctave 29バイト(flawrに感謝!)

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

(1未満でも大丈夫かどうかはわかりません。1未満でなければなりません。しかし、正確に1を引く確率はどれくらいですか...)

MatlabまたはOctave 31バイト

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

1
とてもいいアイデアです!でさらに2バイト節約できますmean(sum(rand(2,4e6).^2)<1)*4
-flawr

4

Java、108バイト

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

4000回の反復。ポイントが単位円の内側にあるたびに0.001が加算されます。かなり基本的なもの。

注:はい、1 πバイト文字に変更することで4バイトを削減できることがわかっています。私はこの方法が好きです。


なぜ9999回反復しないのですか?
オプティマイザー

1
@Optimizer合計を短くします。9999回の繰り返しの場合、代わりに毎回より正確な数値を追加する必要がありますが、これには桁がかかります。
ジオビット

1
数字に「4e5」と「1e-5」を使用すると、別のバイトを保存して精度を向上させることができます。
ヴィルマンタスバラナウスカス

@VilmantasBaranauskasありがとう!私はいつもそれを忘れます:)代わりに4e9と1e-9を使用するのは魅力的ですが、それはかなり時間がかかります
...-Geobits

ヒント:ゴルフをするときは、実際にバイトを減らす必要がありますが、人為的に増やす必要はありません
Destructible Lemon

3

Javascript:62バイト

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

以前の(現在削除されている)javascript回答を使用し、5バイトを削りました。


適切にクレジットを与えるために、cfernの回答リンクできます。
ジョナサンフレッチ

あなたの答えはI / O許可されていないスニペットのようです。投稿を修正または削除してください。
ジョナサンフレッチ

申し訳ありませんが、私は新しいので、現在表示されている以前のソリューションへのリンクを削除する方法を知りませんでした。スニペットに関して:私は完全に同意しますが、それは以前のjavascriptソリューションのコードであり、その理由も無効だと思います。私は私のものをプログラムに変更しました。
グズマンティエ

はい; 以前の回答は無効だったため削除されました-削除を勧める前にあなたの回答を見たので、コメントです。有効な回答を送信した場合は+1。PPCGへようこそ!
ジョナサンフレッチ

2

GolfScript(34文字)

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

オンラインデモ

GSには実際には浮動小数点がないため、これは固定小数点を使用します。固定小数点の使用が少し乱用されるため、繰り返し回数を変更する場合は、10の2倍になるようにしてください。

採用された特定のモンテカルロ法に対するxnorの功績。


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でより良いpiを得ることができますが、我慢する必要があります。


あなたは置き換えることによって、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

ハイライトの1つは8e5、これが表記法を使用できることです。これにより、同じプログラムバイトカウントで最大8e9サンプルまで拡張可能になります。



1

Scala、87 77 66バイト

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

あなたは交換した場合10008000し、250d2e4バイト保存の両方あなたと8倍のサンプル数を増やす
デイブ・シュワルツ

1

Pure Bash、65バイト

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

サンプル数を与えるために4を掛けた単一のコマンドラインパラメーターを受け取ります。バッシュ演算は整数のみであるため、有理数が出力されます。これはbc -l最終的な分割のためにパイプされます:

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

1

ジョー20 19バイト

注:ランダム性を追加したバージョン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. コードを[2つのフロートを読み取り、平方します。registerのi1が2乗の合計より大きい場合にregisterを実行しますu
  2. コードを[ x1 ずつレジスタをインクリメント]に登録しますi
  3. registerの[registerを実行し、register uをインクリメントしmzregister mがregister より大きい場合にregisterを実行するn]にコードを格納しますz
  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

Pyth、19

c*4sm<sm^OQ2 2*QQQQ

入力として目的の反復回数を指定します。

デモンストレーション

Pythには「ランダムな浮動小数点数」機能がないため、即興で演奏する必要がありました。プログラムは、入力、平方、合計よりも小さい2つのランダムな正の整数を選択し、入力の平方と比較します。これは入力に等しい回数実行され、結果は4倍され、入力で除算されます。

関連ニュースでは、まもなくPythにランダムな浮動小数点演算を追加します。ただし、このプログラムはその機能を使用しません。


「結果は、浮動小数点、固定小数点、または有理数として返されるか出力される場合があります」と解釈した場合 自由に、結果の分数の分子と分母を印刷するだけで十分です。その場合:

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バイト

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

ゴルフをしていない:

#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 / with whitespace"または何かを付けて現在のバージョンを保持します)
Destructible Lemon

@DestructibleWatermelonできました!
カールナップ

このソリューションは、前に改行がないと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
なぜ下票なのか?
破壊可能なレモン

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

10進数として:

(exact->inexact(f 10000))

3.13583200307849

1

Fortran(GFortran)84 83バイト

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

オンラインでお試しください!

このコードは非常に悪いです。gfortranが変数Aを0以外の値で初期化することを決定すると失敗します(コンパイルの約50%が発生します)A。次に、Piの同じ値が常に印刷されます。

これははるかに優れたプログラムです。

Fortran(GFortran)100 99バイト

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

オンラインでお試しください!

(各バージョンで1バイトが保存されました。Penguinoに感謝します)。


1
各バージョンで、「DO I = 1,1E3」を「DO I = 1,4E3」に変更し、「A = A + 1」を「A = A + 1E-3」に変更し、「 PRINT *、A / 250 'から' PRINT *、A '
Penguino

はい、確かです!提案をありがとう!
rafa11111

1

Japt、26または18バイト

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

オンラインでお試しください!

オプティマイザーの答えに似ていますが、主にJaptを学習しようとしています。
実行する反復回数を暗黙的な入力として受け取ります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.

1/(1+x^2)(2つの個別のランダムではなく)が許可されている場合、同じロジックで18バイトを達成できます。

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

1
Mh自分でやるのではなく、斜辺を計算させることで数バイト節約できます;-)また、x追加で減らすのではなく、配列の合計を取るために使用できます:o x@MhMr Mr)<1Ã*4/U
ETHproductions

@ETHproductionsニート、私はあなたがMhそのように使えることを知りませんでした、ありがとう!あなたの2つのランダムな答えは、ランダムに1つだけの私の答えとほぼ同じくらい短いです。私はx覚えておいてください、私はゴルフのものをしようとするときに多くの削減を使用する傾向があるので、これは非常に便利になるでしょう。
NIT

1

F#、149バイト

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

オンラインでお試しください!

私が知る限り、F#でこの種の合計を実行Seq.sumByするには、for..to..doブロックを使用するよりも、数値の配列を作成してメソッドを使用する方が短いです。

このコードがs行うことは、1からの浮動小数点数のコレクションを作成し、機能を実行しますfun x->...内の要素数に対してを、結果を合計します。sコレクションには要素があるため、ランダムテストはs何度も実行されます。コレクション内の実際の番号は無視されます(fun x->、ただしx使用されません)。

また、アプリケーションが最初に配列を作成して入力し、次にそれを反復処理する必要があることも意味します。したがって、おそらくfor..to..doループの2倍の速度です。そして、配列の作成により、メモリ使用量はO(f ** k)の領域になります!

実際のテスト自体については、 if then elseステートメント、距離(q()+q()|>Math.Sqrt)を計算し、で切り捨てMath.Floorます。距離が円内にある場合、0に切り捨てられます。距離が円外にある場合、1に切り捨てられます。Seq.sumByメソッドはこれらの結果を合計します。

Seq.sumBy合計したものはポイントではないことに注意してください円の内側の、円の外側の点であることに。そのため、結果を得るにはs(サンプルサイズ)を取り、そこから合計を引きます。

また、パラメータとしてサンプルサイズを取得することは、値をハードコーディングするよりも短いようです。だから私は少し浮気しています...


1

ハスケル、116の 114 110 96バイト

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):あまりにも多くの貴重なバイトを取ると、私はいくつかの発言はほとんど暗号的に強いと線形合同法で乱数の無限リストを生成x↦x*9+1 mod 8^9、でハル・Dobell定理の全期間を持っています8^9

g4の乱数のペアについて、乱数ポイントが円の内側にある場合に得られます[0..8^9-1]これは、使用される式の乗算を排除するためされます。

使用法:

> p 100000
3.14208

オンラインでお試しください!


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.