2016-01-17 11 views
7

私はここに新しいメンバーです。私は日曜日を過ごして、その周りに頭を浮かべています。Pythonでpiを正確に計算できません

私は以前に(それが10週間の大学のモジュールでした)基本の中間レベルにC++でコーディング学ん持つ、パイソンに新たなんです。

私はパイを計算するために反復手法のカップルをしようとしているが、両方は少し不正確まで来ていると私はなぜわかりません。

私が大学で教えた最初の方法 - あなたのうちの何人かは前にそれを見てきたと確信しています。

x=0.0 
y=0.0 
incircle = 0.0 
outcircle = 0.0 
pi = 0.0 
i = 0 
while (i<100000): 
    x = random.uniform(-1,1) 
    y = random.uniform(-1,1) 
    if (x*x+y*y<=1): 
     incircle=incircle+1 
    else: 
     outcircle=outcircle+1 
    i=i+1 
pi = (incircle/outcircle) 
print pi 

これは本質的に、両方の軸で-1から+1までの平面上のランダム(x、y)座標のジェネレータです。次に、x^2 + y^2 < = 1の場合、座標軸によって形成されるボックス内の点が半径1の円の内側にあることがわかります。

ポイントの位置によっては、カウンタがincircleまたはoutcircleの場合に増加します。

piの値は、円の内側と外側の値の比です。座標は無作為に生成されるため、均等に分散させる必要があります。

しかし、非常に高い反復値であっても、私のPiの結果は常に3.65付近にあります。

第2の方法は、ポリゴンがほぼ円になるまで辺の数が増加するポリゴンの円周を計算し、次にPi =円周/直径です。 (コーディングにはmath.cos(Pi)という用語がありますのでPiを使用しているように見えますが、これはPythonで角度を表現するために度を簡単に使用できないためです)。しかし、反復回数が多い場合でも、最終結果は3.20付近で終わるように見えますが、これもやはり間違っています。コードはここにある:

S = 0.0 
C = 0.0 
L = 1.0 

n = 2.0 
k = 3.0 
while (n<2000): 
    S = 2.0**k 
    L = L/(2.0*math.cos((math.pi)/(4.0*n))) 
    C = S*L 
    n=n+2.0 
    k=k+1.0 

pi = C/math.sqrt(2.0) 
print pi 

私のC++のコースを行うとき、私はしかし、私ができる、問題は一般的なものであり、それは数学によるものではないことを告げたが、理由は、コード内で何かをされて、覚えて、正確に覚えていない。それは、乱数の生成や、浮動小数点数の使用の限界、または何か本当に何かと関係があるかもしれません。それだけでも私の数学かもしれません...

問題は何だと思いますか?

TL; DR:パイを計算しようとすると、私は関係なく、私はどのように多くの反復、それに近いが、決して非常に正確に取得することはできません。

(2番目のコードにはS = 2.0 ** kという行がありますが、 'n'を2000より高く設定すると、Sの値が大きすぎて処理できなくなり、コードがクラッシュしますどうすれば修正できますか?)

ありがとう!

+0

これは数学の問題です。 Monte-Carloの方法は、pi自体ではなく、piの近似を与える。 [This](http://rosettacode.org/wiki/Pi#Python)はより正確でなければなりません。 – Rolbrok

+0

私はまた、Pythonが時にはその計算で少し不安定であることに気付きました。たとえば、 'tan(45)degreesを適用すると、1ではなく0.99999 ...を返します。 –

+0

@AshwinGuptaこれは単なるPythonの欠点ではなく、浮動小数点演算を実装する言語です。また、1と等しいtan(45)です。 – Reti43

答えて

7

あなたの最初のバージョンのためのアルゴリズムは、より多くのようになります。

from __future__ import division, print_function 

import sys 
if sys.version_info.major < 3: 
    range = xrange 

import random 


incircle = 0 
n = 100000 
for n in range(n): 
    x = random.random() 
    y = random.random() 
    if (x*x + y*y <= 1): 
     incircle += 1 
pi = (incircle/n) * 4 
print(pi) 

プリント:

3.14699146991 

をこれが接近しています。 nをさらにpiに近づけるように増やしてください。

algorithmは、単位円の4分の1、すなわち、半径が1であることを考慮しています。

四分円の面積のための式は:

area_c = (pi * r **2)/4 

この円を含む正方形の領域のためにその:

area_s = r **2 

rは円の半径です。

今比率は次のとおりです。

area_c/area_s 

代替あなたが得る上記の式は、再arangeと:

pi = 4 * (area_c/area_s) 

はちょうど表し非常に高い数で両方の領域を置き換える、モンテカルロを行きますそれら。通常、ランダムにスローされたダーツの類推がここで使用されます。

+0

ちょっと、ちょうどそれを掲示していた:)。ああ、まあ、とにかくパイソンの人じゃない。 –

+0

中点のポイントと全ポイントの比率は(4倍)、外のポイントだけです。言及すべきです。 –

+0

ああ、ありがとう!わかった。私はちょうどメモリ(1年以上前)からのコーディングをちょうど行っていたことを認めて、それの背後にある基本的な数学を考えるのをやめずに、むしろばかげて、単純に(内接/外接)だと思ったようですが、いくつかの古いファイルを介して、元のC + +コードを発見した、それは確かにここで説明された方法を使用します。再度、感謝します。 –

2

最初の一つは、あなたの計算は、これは、総ポイント数(私の実行で約0.785671)の上に、円の内側に上陸したポイント数である

pi = incircle/1000000*4 # 3.145376.. 

でなければなりません。

半径が1の場合(random.uniform(-1,1))、合計面積は4です。したがって、円の内側に着地したポイントの比率を4倍にすると正しい答えが得られます。

関連する問題