web-dev-qa-db-ja.com

std :: pow(double、int)がC ++ 11から削除されたのはなぜですか?

p ^ q(指数)を計算する効率的な方法、qは整数 を調べ、C++ 98およびC++ 11標準を確認すると、明らかにstd::pow(double, int) C++ 11ではオーバーロードが削除されました。

C++ 98 26.5/6では、double pow(double, int);署名があります。

C++ 11 26.8では、floatdouble、またはlong doubleのペアをとるオーバーロードと、パラメータータイプが混在している場合は、 integer&double、pow(double, double)オーバーロードを選択する必要があること。

これは、以前の意図の明確化ですか、それらはC++ 98で誤って追加されましたか、実際にはC++ 11で削除されましたか、それとも何か他のものですか?

明らかにpow(double, int)バージョンは最適化のための素晴らしい機会を提供するので、それらが削除されるのは奇妙に思えます。コンパイラーは、このような最適化されたオーバーロードを提供するために準拠する標準のままでしょうか?

63
Mark B
_double pow(double, int);
_

仕様から削除されていません。それは単に言い換えられました。現在は[c.math]/p11にあります。計算方法は実装の詳細です。変更された唯一のC++ 03シグネチャは次のとおりです。

_float pow(float, int);
_

これは今度はdoubleを返します:

_double pow(float, int);
_

thisの変更は、C互換性のために行われました。

説明

26.8 [cmath]/p11さんのコメント:

さらに、以下を保証するのに十分な追加のオーバーロードが存在する必要があります。

  1. Doubleパラメータに対応する引数の型がlong doubleである場合、doubleパラメータに対応するすべての引数はlong doubleに効果的にキャストされます。

  2. それ以外の場合、doubleパラメータに対応する引数の型がdoubleまたは整数型である場合、doubleパラメータに対応するすべての引数は事実上doubleにキャストされます。

  3. それ以外の場合、doubleパラメータに対応するすべての引数は事実上浮動小数点にキャストされます。

この段落は、以下を含むオーバーロードのホスト全体を意味します。

_double pow(double, int);
double pow(double, unsigned);
double pow(double, unsigned long long);
_

等.

これらは実際のオーバーロードであるか、制限されたテンプレートで実装されている可能性があります。私はそれを両方の方法で個人的に実装しており、制限されたテンプレートの実装を強く支持しています。

最適化の問題に対処するための2回目の更新:

実装では、オーバーロードを最適化できます。しかし、最適化はのみでなければならないことを思い出してください。最適化されたバージョンは同じ答えを返すはずです。 powのような関数の実装者からの経験は、整数指数を取る実装が浮動小数点指数を取る実装と同じ答えを与えることを確認するために問題に行くときまでに、「最適化」はしばしば遅くなるということです。

デモとして、次のプログラムはpow(.1, 20)を2回出力します。1回はstd :: powを使用し、2回目は積分指数を利用する「最適化された」アルゴリズムを使用します。

_#include <cmath>
#include <iostream>
#include <iomanip>

int main()
{
    std::cout << std::setprecision(17) << std::pow(.1, 20) << '\n';
    double x = .1;
    double x2 = x * x;
    double x4 = x2 * x2;
    double x8 = x4 * x4;
    double x16 = x8 * x8;
    double x20 = x16 * x4;
    std::cout << x20 << '\n';
}
_

私のシステムではこれが出力されます:

_1.0000000000000011e-20
1.0000000000000022e-20
_

または16進表記:

_0x1.79ca10c92422bp-67
0x1.79ca10c924232p-67
_

そして、はい、捕虜の実装者は、ローエンドでこれらすべてのビットを心配しています。

したがって、pow(double, int)を別のアルゴリズムにシャッフルする自由はありますが、私が知っているほとんどの実装者は、非常に小さな積分指数のチェックを除いて、その戦略をあきらめています。そしてその場合、最適化の見返りを最大にするために、浮動小数点指数を使用して実装にチェックを入れるのが通常は有利です。

82
Howard Hinnant