为什么从C ++ 11中删除了std :: pow(double,int)?
在研究有效的方法来计算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中我只能find一对float
, double
或long double
重载,并且明确指出,如果参数types是整数和双float
的混合, pow(double, double)
重载应该是采摘。
这只是澄清了以前的意图,是不正确地添加在C + + 98,他们实际上删除了C + + 11,或其他?
pow(double, int)
版本显然提供了一个很好的优化机会,所以看起来很奇怪,他们会被删除。 编译器是否仍然符合提供这种优化过载的标准?
double pow(double, int);
尚未从规范中删除。 它简单地被重写。 现在住在[c.math] / p11。 它是如何计算的是一个实现细节。 唯一已经改变的C ++ 03签名是:
float pow(float, int);
这现在返回一倍:
double pow(float, int);
这个改变是为了兼容C而完成的。
澄清 :
26.8 [cmath] / p11说:
此外,还应有足够的额外过载来确保:
如果任何对应于double参数的参数的types是long double,则所有对应于double参数的参数都被有效地转换为long double。
否则,如果任何对应于double参数的参数具有doubletypes或整数types,那么与double参数相对应的所有参数将被有效地强制转换为double。
否则,对应于double参数的所有参数都被有效地转换为float。
这一段意味着大量的重载,包括:
double pow(double, int); double pow(double, unsigned); double pow(double, unsigned long long);
等等
这些可能是实际的重载,或者可能使用受限制的模板来实现。 我亲自实施了这两种方式,并强烈支持有限的模板实施。
第二次更新地址优化问题:
该实现允许优化任何过载。 但请记住,优化应该只是这样。 优化的版本应该返回相同的答案。 像pow这样的函数的实现者的经验是,当你花时间去确保你的实现采取一个整数指数给出与浮点指数实现相同的答案时,“优化”往往是较慢的。
作为演示,以下程序使用std :: pow打印两次pow(.1, 20)
,第二次使用“优化”algorithm利用积分指数:
#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
或者用hex表示法:
0x1.79ca10c92422bp-67 0x1.79ca10c924232p-67
是的,pow的执行者真的担心所有这些低端的下降。
所以,虽然自由是在洗牌pow(double, int)
到一个单独的algorithm,我知道大多数实现者已经放弃了这个策略,除了检查非常小的积分指数。 在这种情况下,通过浮点指数来实现这种检查通常是有利的,以便为您的优化降压获得最大的回报。