double pow(double, int);
仕様から削除されていません。単に言い直しただけです。現在は [c.math]/p11 にあります。それがどのように計算されるかは、実装の詳細です。変更された唯一の C++03 署名は次のとおりです。
float pow(float, int);
これは double を返すようになりました:
double pow(float, int);
そして、この変更は C との互換性のために行われました。
明確化:
26.8 [cmath] / p11 言います:
さらに、次のことを保証するのに十分な追加のオーバーロードがあるものとします。
double パラメーターに対応する引数の型が long double である場合、double パラメーターに対応するすべての引数は実質的に long double にキャストされます。
それ以外の場合、double パラメーターに対応するいずれかの引数が double 型または整数型である場合、double パラメーターに対応するすべての引数は実質的に double にキャストされます。
それ以外の場合、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)
、私が知っているほとんどの実装者は、非常に小さな整数指数のチェックを除いて、その戦略をあきらめています。その場合、通常は、浮動小数点指数を使用して実装にそのチェックを入れて、最適化の費用を最大限に活用することが有利です。