2011-04-11 26 views
62

在調查Efficient way to compute p^q (exponentiation), where q is an integer並查看C++ 98和C++ 11標準時,我發現顯然在C++ 11中刪除了std::pow(double, int)重載。爲什麼從C++ 11中刪除了std :: pow(double,int)?

在C++ 98 26.5/6中它有double pow(double, int);簽名。

在C++ 11 26.8所有我能找到的是重載採取對floatdouble,或long double,並明確注意,在參數類型積分&雙的混合物的情況下,在pow(double, double)超載應該是採摘。

這只是澄清了之前的意向,被他們錯誤地添加在C++ 98,被他們居然刪除了C++ 11,還是其他什麼東西?

顯然pow(double, int)版本提供了一個很好的優化機會,所以看起來很奇怪,他們會被刪除。編譯器是否仍然符合提供這種優化過載的標準?

+0

C++ 03呢? – 2011-04-11 20:21:54

+2

優化的好機會是用於實現bignum,而不是用於最有可能支持硬件的'double',也可以使用log + mul + exp解決方案。 – 6502 2011-04-11 20:22:29

+2

@ Ben Voigt:C++ 03與此相匹配。 – 2011-04-11 20:24:18

回答

81
double pow(double, int); 

尚未從規範中刪除。它只是被重新編寫。它現在居住在[c.math]/p11。它是如何計算的是一個實現細節。已更改的唯一的C++ 03的簽名是:

float pow(float, int); 

這現在返回雙:

double pow(float, int); 

而且變化是爲了與C兼容完成。

澄清

26.8 [CMATH]/P11表示:

此外,應再 重載足以確保:

  1. 如果對應於任何參數雙參數的類型爲long double, 則所有參數對應於 雙參數有效地投擲 長雙。

  2. 否則,如果對應於一個雙參數 任何參數的類型爲雙或整數類型, 則對應於 雙參數所有參數都是有效投 翻一番。

  3. 否則,對應雙參數所有參數都是 有效地轉換爲浮動。

這一段意味着重載一大堆,包括:

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

等。

這些可能是實際的重載,或者可能使用受限模板實現。我親自實施了這兩種方式,並強烈支持受限制的模板實施。

二更新來解決問題的優化:

實現被允許以優化任何過載。但回想一下,優化應該是只有那。優化的版本應該返回相同的答案。像pow這樣的函數的實現者的經驗是,當你遇到麻煩時,要確保你的實現採用一個整數指數給出與採用浮點指數的實現相同的答案,那麼「優化」通常會比較慢。

作爲示範下面的程序打印出pow(.1, 20)兩次,使用std ::戰俘,並使用「優化」算法取整指數的優勢第二次一次:

#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)轉換爲單獨的算法,但我知道的大多數實現者已經放棄了該策略,可能除了檢查非常小的積分指數。在這種情況下,通過浮點指數實現檢查通常是有利的,以便爲您的優化降壓獲得最大的回報。

+0

這是尚未發佈的最終版本的變化嗎? – 2011-04-11 20:49:06

+0

不,我會盡力澄清我的答案... – 2011-04-11 21:26:10

+0

你說'pow(double,int);'還沒有被刪除,但我的編譯器似乎認爲它已經存在,我該如何實際訪問它? – crobar 2014-01-24 11:31:58

相關問題