C# を使用して PI の値を計算するにはどうすればよいですか?
私はそれが再帰関数によるものだと思っていました。
私はパフォーマンスについてあまりうるさくはありません。
再帰が必要な場合:
PI = 2 * (1 + 1/3 * (1 + 2/5 * (1 + 3/7 * (...))))
これは、いくつか書き直した後、次のようになります。
PI = 2 * F(1);
F(i):
double F (int i) {
return 1 + i / (2.0 * i + 1) * F(i + 1);
}
Isaac Newton (以前に彼の名前を聞いたことがあるかもしれません ;)) がこのトリックを思いつきました。簡単にするために、終了条件を省略したことに注意してください。実生活では、一種のものが必要です。
使用方法:
double pi = Math.PI;
それよりも高い精度が必要な場合は、アルゴリズム システムと Decimal 型を使用する必要があります。
この非常に優れたガイドをよく見ると、次のようになります。
並列プログラミングのパターン: .NET Framework 4 による並列パターンの理解と適用
ページ 70 で、このかわいい実装を見つけることができます (私の側からの小さな変更があります):
static decimal ParallelPartitionerPi(int steps)
{
decimal sum = 0.0;
decimal step = 1.0 / (decimal)steps;
object obj = new object();
Parallel.ForEach(
Partitioner.Create(0, steps),
() => 0.0,
(range, state, partial) =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
decimal x = (i - 0.5) * step;
partial += 4.0 / (1.0 + x * x);
}
return partial;
},
partial => { lock (obj) sum += partial; });
return step * sum;
}
ここで見られないことに驚いた、本当に古いトリックがいくつかあります。
atan(1) == PI/4 であるため、信頼できる逆正接関数が存在する場合の古さは 4*atan(1) です。
古い西部の 22/7 を汚れのように見せる非常にかわいらしい固定比率の見積もりは 355/113 で、これは小数点以下数桁 (少なくとも 3 または 4 だと思います) まで良好です。場合によっては、整数演算にはこれで十分です: 355 を掛けてから 113 で割ります。
355/113 も簡単に記憶に留めることができます (とにかく一部の人にとっては): 1、1、3、3、5、5 を数え、分母と分子の数字に名前を付けていることを思い出してください (どのトリプレットが行くか忘れた場合)その上、マイクロ秒の思考は通常それをまっすぐにしようとしています)。
22/7 は 3.14285714 を与えることに注意してください。これは 1000 分の 1 が間違っています。
355/113 は 3.14159292 となり、これは 1000 万分の 1 まで間違っていません。
ACC。私のボックスの /usr/include/math.h に対して、M_PI は次のように #define されます: 3.14159265358979323846 これは、おそらくこれで十分です。
PI の推定から得られる教訓は、それを行う方法はたくさんあり、どれも完璧ではないということであり、使用目的によってそれらを分類する必要があります。
355/113 は中国の古い推定値であり、22/7 より何年も前の日付だと思います。学生時代に物理学の先生から教えてもらいました。
さまざまなアルゴリズムの概要:
最初のリンクで Gauss-Legendre-Salamin アルゴリズムに対して主張されている複雑さについてはわかりません (O(N log^2(N) log(log(N))))。
試してみることをお勧めしますが、収束は非常に高速です。
また、非常に単純な手続き型アルゴリズムを再帰的なアルゴリズムに変換しようとする理由がよくわかりません。
パフォーマンスに関心がある場合、制限された精度 (通常、「double」、「float」などの出力が必要) で作業することは意味がないことに注意してください。そのような場合の明白な答えは、値をハードコードします。
PIとは何ですか?円の円周をその直径で割ったもの。
コンピュータグラフィックスでは、最初の点x、yから中心が0,0の円をプロット/描画できます。次の点x'、y'は、次の簡単な式を使用して見つけることができます。x'= x + y / h: y'= y-x' / h
hは通常2の累乗であるため、シフト(またはダブルの指数からの減算)で簡単に除算を実行できます。hはまたあなたの円の半径rになりたいです。簡単な開始点はx=r、y = 0であり、次にcをx <= 0までのステップ数でカウントして、円の4分の1をプロットします。PIは4*c/rまたはPIは4*c / h
深さまでの再帰は、通常、商用プログラムでは実用的ではありませんが、末尾再帰を使用すると、ループとして実装しながら、アルゴリズムを再帰的に表現できます。再帰的検索アルゴリズムは、プロセスのスタックではなくキューを使用して実装できる場合があります。検索は行き止まりからバックトラックして別のパスをたどる必要があります。これらのバックトラックポイントはキューに入れることができ、複数のプロセスがポイントのキューを解除して試行することができます。他のパス。
これが素晴らしいアプローチです(piのメインのウィキペディアエントリから)。これは、上記の単純な式よりもはるかに速く収束し、学習演習として再帰を追求することを目的としている場合は、再帰的なソリューションに非常に適しています。(あなたが学習経験を終えていると仮定して、私は実際のコードを提供していません。)
基本的な式は上記と同じですが、このアプローチでは部分和を平均して収束を加速します。
次のような2つのパラメーター関数pie(h、w)を定義します。
pie(0,1) = 4/1
pie(0,2) = 4/1 - 4/3
pie(0,3) = 4/1 - 4/3 + 4/5
pie(0,4) = 4/1 - 4/3 + 4/5 - 4/7
... and so on
したがって、再帰を調べる最初の機会は、「幅」パラメーターが増加するにつれて(「高さ」がゼロの場合)、その「水平」計算をコーディングすることです。
次に、次の式を使用して2番目のディメンションを追加します。
pie(h, w) = (pie(h-1,w) + pie(h-1,w+1)) / 2
もちろん、これはゼロより大きいhの値にのみ使用されます。
このアルゴリズムの良いところは、スプレッドシートで簡単にモックアップして、徐々に大きくなるパラメーターによって生成された結果を調べるときにコードをチェックできることです。pie(10,10)を計算するときまでに、ほとんどのエンジニアリング目的に十分なpiの近似値が得られます。
Enumerable.Range(0, 100000000).Aggregate(0d, (tot, next) => tot += Math.Pow(-1d, next)/(2*next + 1)*4)
次のように計算します。
x = 1 - 1/3 + 1/5 - 1/7 + 1/9 (... etc as far as possible.)
PI = x * 4
あなたはPiを持っています!!!
これは私が知っている最も簡単な方法です。
PI の値は、Pi の実際の値 (3.141592165......) にゆっくりと収束します。より多くの反復を行うと、より良い結果が得られます。
using System;
namespace Strings
{
class Program
{
static void Main(string[] args)
{
/* decimal pie = 1;
decimal e = -1;
*/
var stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start(); //added this nice stopwatch start routine
//leibniz formula in C# - code written completely by Todd Mandell 2014
/*
for (decimal f = (e += 2); f < 1000001; f++)
{
e += 2;
pie -= 1 / e;
e += 2;
pie += 1 / e;
Console.WriteLine(pie * 4);
}
decimal finalDisplayString = (pie * 4);
Console.WriteLine("pie = {0}", finalDisplayString);
Console.WriteLine("Accuracy resulting from approximately {0} steps", e/4);
*/
// Nilakantha formula - code written completely by Todd Mandell 2014
// π = 3 + 4/(2*3*4) - 4/(4*5*6) + 4/(6*7*8) - 4/(8*9*10) + 4/(10*11*12) - (4/(12*13*14) etc
decimal pie = 0;
decimal a = 2;
decimal b = 3;
decimal c = 4;
decimal e = 1;
for (decimal f = (e += 1); f < 100000; f++)
// Increase f where "f < 100000" to increase number of steps
{
pie += 4 / (a * b * c);
a += 2;
b += 2;
c += 2;
pie -= 4 / (a * b * c);
a += 2;
b += 2;
c += 2;
e += 1;
}
decimal finalDisplayString = (pie + 3);
Console.WriteLine("pie = {0}", finalDisplayString);
Console.WriteLine("Accuracy resulting from {0} steps", e);
stopwatch.Stop();
TimeSpan ts = stopwatch.Elapsed;
Console.WriteLine("Calc Time {0}", ts);
Console.ReadLine();
}
}
}
public static string PiNumberFinder(int digitNumber)
{
string piNumber = "3,";
int dividedBy = 11080585;
int divisor = 78256779;
int result;
for (int i = 0; i < digitNumber; i++)
{
if (dividedBy < divisor)
dividedBy *= 10;
result = dividedBy / divisor;
string resultString = result.ToString();
piNumber += resultString;
dividedBy = dividedBy - divisor * result;
}
return piNumber;
}
それにかんする...
...学習の観点からそれをどのように進めるか。
科学的方法をプログラムすることを学ぼうとしていますか?または本番ソフトウェアを作成するには?コミュニティがこれを問題ではなく、有効な質問と見なしてくれることを願っています。
どちらの場合でも、自分で円周率を書くことは解決された問題だと思います。ドミトリーはすでに「Math.PI」定数を示しています。同じスペースで別の問題を攻撃してください!一般的なニュートン近似または何か洗練されたものを探してください。
次のリンクは、積分としての定義に基づいて円周率定数を計算する方法を示しています。これは、合計の限界として記述できます。これは非常に興味深いものです 。https ://sites.google.com/site/rcorcs/posts/calculatingthepiconstant ファイル「積分としての円周率」は、この投稿で使用されるこの方法を説明しています。
@トーマス・カメイヤー:
Atan(1.0) は非常に頻繁にハードコーディングされているため、ライブラリの Atan 関数を呼び出している場合、4*Atan(1.0) は実際には「アルゴリズム」ではないことに注意してください (かなりの数が既に提案されており、Atan(x) をそれのシリーズ(または無限積)、次にx = 1で評価します。
また、数十ビットよりも高い精度で pi が必要になるケースはほとんどありません(これは簡単にハードコーディングできます!)。私は数学のアプリケーションに取り組んできました。いくつかの (非常に複雑な) 数学オブジェクト (整数係数を持つ多項式) を計算するために、実数と複素数 (pi の計算を含む) を最大 1 の精度で計算する必要がありました数百万ビット...しかし、これは「実生活では」あまり頻繁ではありません:)
次のコード例を参照できます。
どのような運用シナリオでも、必要な小数点以下の桁数まで値を検索し、クラスがアクセスできる場所に「const」として格納することをお勧めします。
(科学的な「Pi」固有のソフトウェアを作成している場合を除きます...)
逆正接のテイラー級数展開に基づいて π を計算する方法を説明しているこの論文が気に入っています。
この論文は、次の単純な仮定から始まります。
Atan(1) = π/4 ラジアン
Atan(x) は、テイラー級数を使用して反復的に推定できます。
atan(x) = x - x^3/3 + x^5/5 - x^7/7 + x^9/9...
この論文は、これが特に効率的ではない理由を指摘し、この手法に多くの論理的な改良を加えています。また、π を数千桁まで計算するサンプル プログラムも提供しており、必要な無限精度の数学ルーチンを含むソース コードを完備しています。
まず、C# は .NET フレームワークの Math.PI フィールドを使用できることに注意してください。
https://msdn.microsoft.com/en-us/library/system.math.pi(v=vs.110).aspx
ここでの優れた機能は、使用するか、計算結果と比較できる完全精度の double であることです。その URL のタブには、C++、F#、および Visual Basic の同様の定数があります。
より多くの桁数を計算するには、独自の拡張精度コードを記述できます。コーディングが速く、適度に高速で簡単にプログラミングできるものは次のとおりです。
Pi = 4 * [4 * arctan (1/5) - arctan (1/239)]
Wolframには、この式と、1項あたり50桁などの驚くほど高速で収束するものを含む、他の多くの式があります。
public double PI = 22.0 / 7.0;