なぜな`int pow(int盤,int指数)を標準C++ライブラリ?
-
25-09-2019 - |
質問
っていうなかできないティへ簡単にアクセスできます。があることにより、C++ pow
機能しない実力"に"機能以外は何も float
s double
s?
ピックアップしました。実装は自明であるが、私のように立つ仕事をしているという標準的な図書館があります。強力関数(すなわち取り扱うオーバーフローの一部、一貫した明確な道ではありませんの書き出します。
解決
実際のところ、それがない。
ではC ++ 11はpow(int, int)
のテンプレート実装がある---、さらに一般的なケースでは、(7)を参照します
http://en.cppreference.com/w/cpp/numeric/math/ POWする
編集:実際にそこにあるよう純粋主義者は、これは正しくないと主張するかもしれタイピングを使用し、「昇格」。一つの方法または別のは、一つはint
パラメータに、正しいint
結果、またはエラーを取得します。
他のヒント
としての C++11
, 特別の場合に追加されたスイートの力機能(その他)。 C++11 [c.math] /11
国は、すべての float/double/long double
過負荷(マを重視し、言い換え):
また、または追加の過負荷を確保するために十分なものでない 場合引数に対応する
double
パラメータ型double
または整数タイプ、全ての引数に対応するdouble
パラメータを効果的にキャストdouble
.
なので、基本的には、integerパラメータにアップグレードするdoubleを行います。
以前 C++11
したがまだ)、整数が過負荷になりました。
私は、クリエイターの C
も C++
の日の作成(もん am 古く、その一部は、ANSI/ISO委員会が作成した基準は必ずしも意見は私の一部です。と思ってい 通知 の意見ですが、私の妻すばやく奨励するために必要なんて間違った前:-)
仮定し、その分おります。
I 容疑者 その理由の前ANSI C
なかったですが全く不要です。がで高い評価を受けつつも、常に完璧に良いこの整数国(倍で変換した後に整数を確認するために、整数型オーバーフローは、伏流変換前).
第二に、もうひとつごうひとつ忘れてはいけないのであることを目的 C
たとして システム プログラミング言語でのかどうか疑問の浮動小数点が望ましいですがパワーアップ。
以来、その初期使用の場合のためのコUNIXの浮動小数点いて次のどちらがいいでしょうか?BCPL、C、また利用のための権限ではない浮動小数点でのすべてからいたしました。
ちなみに、一体力事業者であろうがしてバイナリのオペレーターによる図書館。いす整数と
x = add (y, z)
がx = y + z
-の 適切な言語 ではなく、図書館があります。
第三に、以降の実施体力が相対的に自明なので、ほぼ確実に、その開発言語によって、より利用時間を提供するより有益なもの(下記参照メントの機会です。
それにも関連するの C++
.を実施した効果的だ翻訳される C
コードで越しの多くの属性 C
.その意図した-C-クラスは-C-クラスが---ちょっとビットのインストール数学は苦手なんですよ。
している理由はありませんでしたが追加される前に水準 C++11
, することを覚えておいて基準設定機関おいて特定のガイドラインに従います。例えば、ANSI C
した具体的にはう任務ィ既存の実践 ない 作成した単語をテンポよく表示。その他、できると思っていなかった彼のこれまAda:-)
後の反復の基準にも特定のガイドラインのはたらきを理由書類(理由をもとに、委員会決定者は、理由のための言語)。
例えば、 C99
理由書は具体的にはを進めていますの C89
基本理念を制限できるものを追加。
- では言語を小さくシンプルです。
- 提供方法が確立されてきているものです。
ガイドライン(必ずしもその 特定の もそれらの個人のワーキング-グループの活動が制限さ C++
委員会その他全てのISO団体に設置されています。
また、基準設定機関かることがあり 機会費用 (経済的な意味を持つ用語で見た日を設定してください)全ての決断に愛着を持っています。例えば、機会費用の購入が10,000ドルのザ-ゲーム機はコーディアルの関係(またはそ すべての 報道関係のおその他の半分を六ヶ月くらい通いました。
エリック-Gunnerson説明していることを自 -100ポイントの説明 理由としては、もんで加えマイクロソフト製品-基本的特徴を開始100ポイントの穴ではなかなかのビット値にする場合もあります。
つまりいただけますでしょうかい体力事業者(正直、半アメリカ-サンフランシスコがホイップに十分またはマルチスレッドに追加されます。自分自身にあります。て、後者においてmuckつの異なる実装の下で,Windows上でもプログラム
いま、何千もの収集は、標準ライブラリ(正btrees、赤-黒木、辞書にあたり、任意のマップなど)がどの理由:
標準は、条約実施者およびプログラマを交換してください。
数体の標準化団体かに上回のプログラマとともに、そのプログラマを良く理解していない機会です。合うものを加え、次の基準 C++
う C++215x
ろに本格実施することが計画されてコンパイラの開発三百年後。
とにかく、これはまさに私にぴったりなば)の思想するものとする。場合にのみ投票された拠点の量よりも品質もすぐにブローの皆さまに。さ聴:-)
の他の固定幅積分型、ほぼすべての入力ペアオーバーフローのタイプだった。どの標準化する機能な有用な結果では、大多数の可能な入力?
おいて大きな整数タイプのための機能を有し、最も大きな整数の図書館に提供します。
編集: にコメントのstatic_rtti書き込みます"ほとんどの入力がでオーバーフロー?同様にexpダブルpowんなもの?)" こが間違っています。
残そうではありませんかほ exp
, その横の点をもう実際に私の場合より強い)、 double pow(double x, double y)
.何部分(x,y)のペアはこの機能を果たしていな(つまり、単なるオーバーフローまたは伏流)?
いう点のみの小さな部分の入力に対する pow
意味をなでるのに十分ない:xが正|y| <=1、 pow
ないオーバーフローまたは伏流.これはポスト全ての浮動小数点のペア(その中からちょうど半分にあた非NaNの浮動小数点数が正の、半分以下の非NaN浮動小数点の数値未満の1)です。あこ 多く その他の入力に対する pow
作用の結果、きちんと把握で少なくとも一四半期のすべての入力できるモデルです。
今振り返ってみたいと思い固定幅(非bignum)整数の発電機能です。何部入力はでないだけでオーバーフロー?最大限の意味のある入力ペアに拠点を明記してくださ指数unsigned.この方法は、基盤指数の両方 n
ビット幅です。できます行きの部分を入力することに意味があることになります:
- た場合の指数を0または1、その他の拠点で意義深いものでした。
- た場合の指数が2以上のを押し付けるのではなく、その拠点以上2^n/2)を作ることである。
このように、2^(2n)の入力ペア以下の2^(n+1)+2^(3n/2)意味のある結果を出せる.いうのが最も一般的使用の32ビット整数を表するとともに、1/1000の一部を入力ペアるだけでなくオーバーフロー.
とにかくint型のすべての整数の力を表現する方法はありませんので。
>>> print 2**-4
0.0625
そのことも興味深い質問です。一つの引数んの議論は、シンプルな明らかな戻り値は、引数になります。みんなで数えてみように、hypthetical int pow_int(int, int)
機能が失敗します。
- オーバーフロー
- 結果は未定義
pow_int(0,0)
- 結果はできませんで表される
pow_int(2,-1)
この機能は、少なくとも2つの故障モードがある。整数で表すこれらの価値観、行動の機能これらの場合も定める必要があるのは、標準の、プログラマーが必要となる場合があるさをしっかりと認識しての機能を取り扱うこと。
全体の機能を行うのみで良識あるオプションです。のプログラマが使用できるの浮動小数点のバージョンのすべてのエラーレポート可能です。
短い答えます:
pow(x, n)
は自然数にn
の専門は、多くの場合、の時のパフォーマンスのために有用です。しかし、標準ライブラリのジェネリックpow()
はまだかなり動作します(の驚く!の)だけでなく、この目的のために、それは、ポータブルとしてかつ簡単とすることができるように、標準Cライブラリのできるだけ含めることが絶対的に重要です可能性として実装します。一方で、それは私が誰も組み込みプラットフォームのいくつかの種類で使用して計画されていないかなり確信しているC ++標準ライブラリやSTL、であることから、すべてでそれを停止しません。
さて、長い答えを。
pow(x, n)
は自然数にn
を専門とすることにより、多くの場合、はるかに高速に行うことができます。私は、ほぼすべてのプログラムI書き込みのために、この機能の私自身の実装を使用しなければなりませんでした(私はC言語で、数学的プログラムの多くを書きます)。専門的な操作はO(log(n))
時間で行うことができますが、n
が小さい場合には、単純な線形バージョンが高速になります。ここでは、両方の実装があります:
// Computes x^n, where n is a natural number.
double pown(double x, unsigned n)
{
double y = 1;
// n = 2*d + r. x^n = (x^2)^d * x^r.
unsigned d = n >> 1;
unsigned r = n & 1;
double x_2_d = d == 0? 1 : pown(x*x, d);
double x_r = r == 0? 1 : x;
return x_2_d*x_r;
}
// The linear implementation.
double pown_l(double x, unsigned n)
{
double y = 1;
for (unsigned i = 0; i < n; i++)
y *= x;
return y;
}
タグ(
x
の結果は、しばしばpow(double x, unsigned n)
は。れるように、約二重に収まるので、私はダブルスとしてpow(double, double)
と戻り値を左)
(はい、pown
は再帰的であるが、最大スタックサイズはほぼ同じlog_2(n)
とn
は整数になるので、スタックを破壊することは絶対に不可能である。n
は、64ビットの整数である場合、それはあなたについての最大スタックサイズを与えます64. のないのハードウェアだけで深い3〜8関数呼び出しを行って、ハードウェアスタックといくつかの危険なのPICを除き、このような極端なメモリの制限があります。)
は、パフォーマンスのために、あなたは庭の様々なpow(double, double)
ができるものによって驚かれることでしょう。私は、同じ繰り返し回数とx
にn
と私の5歳のIBMのThinkPadに億反復をテストし、このシナリオ、pown_l
のウォンでは10に等しいです。 glibcのpow()
が12.0ユーザー秒かかりました、pown
は7.4ユーザー秒かかりました、そしてpown_l
は6.5ユーザー秒かかりました。そのためには、あまりにも驚くことではありません。私たちは、多かれ少なかれ、これを期待していた。
そこで、私はx
は(私は2.5に設定)一定であるしましょう、と私は0から19まで億回をn
をループ。今回は、全く予想外、glibcのpow
は勝った、と地すべりによって!それだけで2.0のユーザ秒かかりました。私pown
は9.6秒を要し、かつpown_l
は12.2秒かかりました。ここで何が起こったのか?私は見つけるために別のテストをしました。
私だけx
で上記と同じことをしたが万人に等しいです。今回は、pown
は9.6sで勝ちました。 pown_l
は12.2Sを取り、glibcのPOWは16.3sを取りました。さて、それは明らかです! glibcのpow
を行い、より良い3よりx
が高いときx
は低いが、最悪の場合に。 x
が高い場合、pown_l
が行う最高n
が低く、ときpown
が行う最高x
が高いときます。
だからここに三つの異なるアルゴリズム、適切な状況下で、他よりも優れて行うことがそれぞれ可能です。だから、最終的には、最も可能性の高い使用するpow
を使用しますが、正しいバージョン<はEM>がの価値は、それを使用して、すべてのバージョンを持つにしている計画は素敵なあなたであるかに依存します。実際には、あなたもこのような機能を持つアルゴリズムの選択を自動化することができます:
double pown_auto(double x, unsigned n, double x_expected, unsigned n_expected) {
if (x_expected < x_threshold)
return pow(x, n);
if (n_expected < n_threshold)
return pown_l(x, n);
return pown(x, n);
}
限りx_expected
とn_expected
として定数は、おそらく他のいくつかの注意点とともに、コンパイル時に決定され、最適化コンパイラの価値は自動的に全体pown_auto
関数呼び出しを削除し、3の適切な選択と交換しますその塩アルゴリズム。あなたが実際にしようとしている場合、私は正確にのコンパイルのしようとしなかったので(今、の使用のこの、あなたはおそらく何私、それをおもちゃに少しを持っています「上に書かれたD;))
一方、glibcのpow
の作業を行い、glibcのは、すでに十分な大きさです。 C標準は、(実際には組み込み開発者はどこにでも、一般的にそのglibcのは、すでに彼らのためには大きすぎる同意)、およびすべてのシンプルなためならば、それは移植できないことができ、様々なの組み込み機器のに含め、移植できるようになっています数学関数は、それがは使用であるかもしれない<全角>すべての代替アルゴリズムを含める必要があります。だから、それはC標準ではない理由です。
脚注:時間のパフォーマンステストでは、私は、私の関数にはそうそう、私のシステム上でコンパイルはglibc(archlinux)に使用されたものを、より悪くない場合は、に匹敵することがあり、比較的寛大な最適化フラグ(-s -O2
)を得ました結果はおそらく公正で。より厳密なテストのために、私は自分自身をglibcをコンパイルする必要があるだろうと私ははreeeally はそれを行うように感じることはありません。私はそれが仕事であっても、かかる時間を覚えて、Gentooを使用するために使用され、の自動化されたの。結果は決定的(またはむしろ決定的)私にとっては十分です。あなたはこれを自分で行うには、もちろん歓迎のだ。
ボーナスラウンド:すべての整数にpow(x, n)
の専門正確な整数出力が起こるんれ、必要な場合は、のインストのです。 P ^ N要素を有するN次元のアレイのメモリを割り当てる考えます。 1はおそらくランダムに発生するセグメンテーション違反になりさえて、p ^ N降ります。
C ++は、追加のオーバーロードを持っていないことが理由の一つは、Cとの互換性がある。
C ++ 98がdouble pow(double, int)
のような機能を持っていますが、これらはC99は、それらが含まれていなかったという議論でC ++ 11で削除されています。
のhttp:// WWW。 open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3286.html#550する
もう少し正確な結果もわずかの異なるの結果を得ることを意味入手ます。
世の中は常に進化するなどのプログラミング言語までの 第四部の小数TR1を追加します機能 <math.h>
.二つの家族のこれらの機能が利益その問題について:
- の
pown
機能する浮動小数点数をとるintmax_t
眠しました。 - の
powr
機能する二つの浮動小数点数(x
やy
や計算x
の電力y
の式exp(y*log(x))
.
この標準のねずみなこれらの特徴を十分に有できたことは大きな成果であり、標準図書館があります。しかし、合理的であるこれらの機能のすすめ ISO/IEC/IEEE60559:2011年 標準バイナリおよび浮動小数点数です。どちらともいえないいえ"基準"が続いた時にC89が、今後の発展 <math.h>
れによって大きく影響を受ける今後の進化の ISO/IEC/IEEE60559 標準装備。
なお、第四部の小数点以下の桁数TRん含まれてC2x(次の主要なC改訂)に対する付属としては、オプションの特徴です。もありませんせい意図を知らにこのTR将来のC++に改訂される。
1までの一部の事業当事業におきましては、業務の進捗文書 こちらの.
おそらく、プロセッサのALUは、整数のような機能を実装していませんでしたが、そのようなFPU命令があるので(スティーブンが指摘するように、それはだ、実際にペア)。それは整数演算を使用してそれを実装するよりも、実際に速くオーバーフローとキャストバックのために、その後倍増するキャスト、ダブルスとの通話POW、テストとなりましたので。
(一つには、対数は乗算に力を減らすが、整数の対数は、ほとんどの入力の精度の多くを失う)
スティーブンは、現代のプロセッサで、これはもはや真実である右のことではありませんが、Cの標準数学関数を選択したとき(C ++は単にC関数を使用)今20歳で、何?
であります非常に単純な理由ます:
5^-2 = 1/25
STLライブラリ内のすべてのものが最も正確な、強力なスタッフ想像に基づいています。確かに、int型はゼロ(1/25から)に戻りますが、これは不正確な答えになります。
私はそれがいくつかのケースでは奇妙な、同意します。