Mar*_*k B 63 c++ c++-standard-library 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所有我能找到的是重载采取一对float,double或者long double和一个明确的注意,在参数类型积分和双重的混合物的情况下,在pow(double, double)过载应挑选.
这只是对前一个意图的澄清,如果它们在C++ 98中被错误地添加了,它们是否真的在C++ 11中删除了,还是别的?
显然,该pow(double, int)版本提供了一个很好的优化机会,所以它们被删除似乎很奇怪.编译器是否仍然符合标准以提供这样的优化过载?
How*_*ant 82
double pow(double, int);
Run Code Online (Sandbox Code Playgroud)
尚未从规范中删除.它简单地被重写了.它现在住在[c.math]/p11.如何计算是一个实现细节.唯一改变的C++ 03签名是:
float pow(float, int);
Run Code Online (Sandbox Code Playgroud)
现在返回双倍:
double pow(float, int);
Run Code Online (Sandbox Code Playgroud)
而这种变化是为了与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);
Run Code Online (Sandbox Code Playgroud)
等等
这些可能是实际的重载,或者可能使用受限模板实现.我亲自实现了它,并强烈支持受限制的模板实现.
第二次更新以解决优化问题:
允许实现优化任何过载.但请记住,优化应该只是那样.优化版本应该返回相同的答案.像pow这样的函数的实现者的经验是,当你遇到麻烦以确保你的实现采用积分指数给出与采用浮点指数的实现相同的答案时,"优化"通常较慢.
作为演示,以下程序打印pow(.1, 20)两次,一次使用std :: pow,第二次使用"优化"算法利用积分指数:
#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';
}
Run Code Online (Sandbox Code Playgroud)
在我的系统上打印出:
1.0000000000000011e-20
1.0000000000000022e-20
Run Code Online (Sandbox Code Playgroud)
或者以十六进制表示法:
0x1.79ca10c92422bp-67
0x1.79ca10c924232p-67
Run Code Online (Sandbox Code Playgroud)
是的,pow的实现者真的确实担心所有这些低端的比特.
因此,虽然可以自由地pow(double, int)转移到单独的算法,但我知道的大多数实现者已经放弃了该策略,可能的例外是检查非常小的积分指数.在这种情况下,通常使用浮点指数将检查放入实现中是有利的,以便为您的优化降压获得最大的收益.