63

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 で見つけたのはfloat、 、double、またはのペアを取るオーバーロードlong doubleと、整数と倍精度のパラメーター型が混在している場合は、pow(double, double)オーバーロードを選択する必要があるという明示的なメモだけでした。

これは以前の意図を明確にしただけですか? C++98 で誤って追加されたのでしょうか? C++11 で実際に削除されたのでしょうか?

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

4

1 に答える 1

84
double pow(double, int);

仕様から削除されていません。単に言い直しただけです。現在は [c.math]/p11 にあります。それがどのように計算されるかは、実装の詳細です。変更された唯一の C++03 署名は次のとおりです。

float pow(float, int);

これは double を返すようになりました:

double pow(float, int);

そして、この変更は C との互換性のために行われました。

明確化:

26.8 [cmath] / p11 言います:

さらに、次のことを保証するのに十分な追加のオーバーロードがあるものとします。

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

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

  3. それ以外の場合、double パラメーターに対応するすべての引数は実質的に float にキャストされます。

この段落は、次のようなオーバーロードのホスト全体を意味します。

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

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

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

実装では、オーバーロードを最適化できます。しかし、最適化はそれだけであるべきだということを思い出してください。最適化されたバージョンは同じ答えを返すはずです。pow のような関数の実装者の経験によると、整数の指数を使用する実装が浮動小数点の指数を使用する実装と同じ答えを返すように問題を解決しようとすると、「最適化」が遅くなることがよくあります。

デモンストレーションとして、次のプログラムは 2 回出力しますpow(.1, 20)。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 の実装者は、これらすべての下位ビットについて本当に心配しています。

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

于 2011-04-11T20:39:06.677 に答える