C ++ 11、14、17、または20は、piの標準定数を導入しますか?


170

CとC ++のpiの数値にはかなりばかげた問題があります。私が知る限り、でM_PI定義されてmath.hいることは、どの規格でも要求されていません。

新しいC ++標準では、標準ライブラリに複雑な数学の多くが導入されました-双曲線関数、std::hermiteおよびstd::cyl_bessel_i、さまざまな乱数ジェネレータなど。

「新しい」標準のいずれかがパイの定数をもたらしましたか?そうでない場合-なぜですか?この複雑な数学はそれなしでどのように機能しますか?

私はC ++のpiに関する同様の質問を認識しています(それらは数年前のものであり、標準から古くなっています); 問題の現状を知りたいのですが。

なぜ C ++にはまだpi定数がないのに、もっと複雑な数学がたくさんあるのという理由にも非常に興味があります。

UPD:自分でpiを4 * atan(1)またはacos(1)またはdouble pi = 3.14として定義できることを知っています。承知しました。しかし、なぜ2018年に私はまだそれをしなければならないのですか?標準の数学関数はpiなしでどのように機能しますか?

UPD2:2019年7月にケルンで開催されたC ++委員会のこの出張レポートによると、提案P0631(数学定数)がC ++ 20に受け入れられました。つまり、ついに標準ライブラリに数piが含まれるようになります!


最高のプラットフォーム非依存pi定数などの古い質問の存在に気付きましたか?。それらが古くなっていると心配する場合は、C ++ 17などに基づいて回答を求める彼らに賞金をいつでも設定することができます。そうすれば、すべての回答が1か所にまとめられます。なぜそれでも良い質問ですが、おそらくこれはなぜかに焦点を当てており、最新の質問は既存の質問に対する報奨金であるべきです。
Shafik Yaghmour

C ++ 20は私が知っている限りpi定数を追加したので、新しい答えを追加する価値があると思う
Guillaume Racicot

@GuillaumeRacicot私は質問を更新しました。C ++ 20はまだ正式にリリースされていないため、対処する必要があるかどうかはわかりません。
Amomum

@GuillaumeRacicot:1つ追加するのは少し遅れます…
Davis Herring

回答:


101

C ++ 17までの piは、言語に導入された定数ではなく、首の痛みです。

私はブーストを使用していて、128ビットでも十分に大きい小数点以下の桁数でpiを定義しているので、幸いですlong double

Boostを使用しない場合は、自分でハードコーディングしてください。三角関数でそれを定義することは魅力的ですが、そうすることはできませんconstexpr。三角関数の精度はまた、任意の標準Iのノウハウによって保証されていない(CFstd::sqrt)ので、本当にあなたがそのような機能に頼る確かに危険な地面の上にあります。

メタプログラミングを使用constexprしてpiの値を取得する方法があります。http://timmurphy.org/2013/06/27/template-metaprogramming-in-c/を参照してください


C ++ 20からいくつかの朗報。そこであるためdefininition piは。C ++ 20は、いくつかの数学定数をに追加し<numbers>ます。例えば、std::numbers::piあるdoubleタイプ。

リファレンス:https : //en.cppreference.com/w/cpp/numeric/constants


9
@Lundin:しかし、constexpr残念ながらそれは許されないので、「トリガー関数を使用して定義するのは面倒です」と私が言うのはそのためです
バトシェバ2018

9
なぜそれが重要なのですか?Piは定数であり、変更や実装固有の変更は行われません。値を(必要に応じてconstオブジェクトで)重要doubleな桁数(または、架空の本当に長いlong doubleが気になる場合はとんでもない数)に書き出すだけです。
R .. GitHub ICE HELPING ICEを停止

10
@R ..私がそれに関して持っている問題は、今やばかげているように見えることですが、20年ほどで完全に正気になることができます。(Bill Gatesの640kが思い浮かびます)。私はBoostがアーキテクチャーの進化についていくことを信頼しています。
バトシェバ2018


10
@KonradRudolph:範囲縮小を実装する場合、高精度のpiが重要です。例えば、x86 /のx87の内部パイ定数(完全な64ビットの仮数)に小さな入力の最悪の場合の誤差のリードfsinの指示 「正しい未満の4ビットを残して最後の場所で約1.37京単位」、そしてそれはの範囲の縮小が複数回循環する大規模な入力の場合はさらに悪い。これはlong double、C ++で使用される定数にいくらか接しているが、とにかくきちんとしている。
Peter Cordes

31

他の人は言っていませんstd::piが、正確なPI値が必要な場合は使用できます:

constexpr double pi = std::acos(-1);

これはC ++の実装がからPIの正しく丸めた値生成することを前提としacos(-1.0)共通だが保証するものではありません

そうではありませんconstexprが、実際には、gccやclangなどの最適化コンパイラがコンパイル時に評価します。constただし、オプティマイザが適切に機能することを宣言することが重要です。


2
acos()関数はで無限の勾配をもつため、これは危険x = -1です。したがって、このメソッドはacos()実装に依存して、基本的に正確な-1引数のケースを明示的にキャッチし、正しい定数を直接返します。4*atan(1)数学的にはるかに堅牢なものを使用することをお勧めします(適切に動作する勾配x = 1と4の乗算は常に浮動小数点演算で正確です)。
cmaster

1
std::acos定数式での使用は許可されていません。clangはこれをエラーとして報告します。これは非準拠の拡張機能であり、最終的にはgccで修正する必要があることに注意してください。詳細については、この回答を参照してください。
badola

31

C ++ 20までは、いいえ、どの標準もpi(π)を表す定数を導入していません。あなたのコードで数を概算することができます:

constexpr double pi = 3.14159265358979323846;

例えば、C#などの他の言語は持っている定数は自分たちのライブラリに宣言しました。

更新: C ++ 20以降、実際pi<numbers>ヘッダー内で宣言された定数があります。次の方法でアクセスしますstd::numbers::pi


6
inlineC ++ 17 + を追加することもできます。
デュプリケータ

8
た。賛成投票してください。ただし、定義は、の定義が異なるプラットフォームでも不正確になりやすいことに注意してくださいdouble。C#はdouble型が固定されているので簡単です。私がC ++標準委員会にいた場合、次のようなものを提案しますstd::constants<double>::pi
バトシェバ

11
@Deduplicatorはconstexprも暗黙的にインラインではありません...?
2018

4
@R。十分に公平ですがstd::numeric_limits<double>::is_iec559;、その場合は静的にアサートする必要があります。私が告白するのは、これが私の「マスターヘッダー」にあるものです。正式には、すべての浮動小数点型を個別にチェックする必要があることに注意してください。IEEE754であるからといって、すべてがそうであるとは限りません。
バトシェバ2018

2
@DanielScheplerでは、その「数」は何であることになっているのでしょうか。16の基数を持つ二重の数があることを知りませんでした。
BЈовић

29

M_PI言語標準ではない場合でも「標準」によって定義されます:X / Open System Interfaces拡張機能を備えたPOSIX(これは非常に一般的にサポートされ、公式のUNIXブランド化に必要です)。

それは(まだ)C ++ 20で何ができるかは定かではありませんが、あなたが尋ねたので:それはおそらくそのような定数を持つでしょう。このペーパーは、C ++ 20機能の最終ラウンド(2019年8月の委員会ドラフト用)にマージされました。

具体的には、std::numbers::pi(タイプdouble)と、異なる浮動小数点タイプが必要な場合に使用できる変数テンプレートの両方がありますstd::numbers::pi_v<float>。定数の完全なリストは[numbers.syn]にあります。


必要に応じて編集内容を自由に変更してください。後世のために、ここに新しい定数の実際のスペルを追加したかっただけです。
バリー

12

ドメイン全体に広く適用できるpiを定義する明確なタイプがないため、これは明らかに良いアイデアではありません。

もちろん、Piは無理数なので、どの C ++型で正しく表すことができません。したがって、自然なアプローチは、利用可能な最大の浮動小数点型でそれを定義することであると主張するかもしれません。ただし、最大の標準浮動小数点型のサイズはlong doubleC ++標準では定義されていないため、定数の値はシステムによって異なります。さらに悪いことに、作業タイプがこの最大タイプではないプログラムの場合、piの使用ごとにパフォーマンスコストがかかるため、piの定義は不適切です。

また、プログラマーがpiの値を見つけて、使用に適した独自の定数を定義することは簡単です。そのため、数学ヘッダーに含めることには大きな利点はありません。


10
C ++ 14は可変テンプレートを提供してくれました。彼らが何のためにあるのではないですか?
Amomum

21
真の委員会メンバーのように話され、明確な道筋が示されているにもかかわらず、それが実行できないすべての方法について話します。 驚くほど関連性の高い変数テンプレートの例をご覧ください。私はあなたの答えが悪いとは思わないが、それがC ++の未来の支配を非常に優柔不断な委員会に手渡したことに対する後悔に対するBjarne Stroustrupの永遠の憂鬱を助けることはないと私は確信している。
2018

4
@snb私piは、多相定数を作成することが明確な前進の道であることに同意します-Hindley -Milner型推論の言語で。Haskellでは、私たちは常に持っていたpi :: Floating a => aので、それがpi自動的に値を持っているでしょう3.1415927ではFloat文脈、3.141592653589793Doubleコンテキスト、およびπシンボリック計算コンテキストで。しかし、テンプレートパラメータを明示的にインスタンス化する必要があるのでしょうか。特に、固定long doubleされた実装でほとんどのアプリケーションで同じ結果が得られる場合は、少し厄介に思えます。
leftaroundabout

2
@leftaroundabout書くことauto a = pi<float>;は完全にうまく、確かにもっと読みやすく、悪名高いと思います4*atan(1)
Amomum

1
うーん、私はミスクリックでこれに反対票を投じたので、元に戻すことはできません。ごめんなさい。これは、委員会が追加されなかった理由のかなり良い説明に+1するに値します。たとえ私が個人的には、人々がすでに指摘している理由から根本的に欠陥があると私が思ったとしてもです。
モニカの訴訟に資金を提供

-1

編集-物議を醸すことが判明したため、必要な用語を削除します。それは絶対的な用語のあまりにも多くです。

C ++は大きくて複雑な言語です。そのため、標準委員会には強く必要なものだけが含まれています。Boostのように、非言語の標準ライブラリにできる限り任せます。
boost :: math :: constants


29
もちろん、std::hermiteand 、and std::cyl_bessel_istd::coshand std::mersenne_twister_enginestd::ranlux48and std::cauchy_distributionstd::assoc_laguerreand std::betaallは絶対に必要です。私たちは皆、毎日それらを使用しています!
Amomum

2
委員会自体でさえ、彼らが投票するすべてのものは「絶対に必要」であるという考えを承認することはできなかったと思います。それは必要性についてではなく、言語に付加価値を付けることについてです。プログラムを作成するために標準ライブラリではほとんど何も必要ありません。そのため、コア言語のほとんども同様に放棄することができます(チューリングターピット、つまり)。piの定数を含めることの価値については議論の余地がありますが、必要がないためにそこにないという考えは水を保持しません。
Jeroen Mostert

私に文句を言わないでください、私は単に標準化委員会を引用しています。C ++ 11標準にどの程度のブーストを含める必要があるかについて、長いオープンな議論がありました。このような小さなサブセットがそれを作った理由は、コンパイラの作者がどれだけ多くのテストが含まれているかについて不平を言ったからです。したがって、何かが規格に含まれている場合、誰かがそれを標準化する必要があると考えたため、そこにあります。理由がわからないからといって、理由がないということではありません。
Tiger4Hire 2018

1
@ Tiger4Hireすべての理由があると確信していますが、より複雑なものがたくさんあるときにpiの定数が追加されなかった理由を理解できません。定数は、変数テンプレートを使用して簡単に作成でき、コンパイラの作成者による多くのテストを必要としません。
Amomum 2018

@Amomum:はい、piを追加することは大きな勝利のための小さなオーバーヘッドのようです。心から、個人的にはstd :: math :: constantsの前にstd :: networkを見たいと思います。
Tiger4Hire 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.