2016-07-11 147 views
0

我正在寫一個函數,我必須計算一個數的階乘並對它們進行操作。函數的返回值應該很長,所以我認爲做所有操作會更好長格式。如果我錯了,請糾正我。tgamma()long long類型轉換

tgamma()函數本身以科學計數法返回正確的值。但是,當函數返回的值被「長時間」類型化時,tgamma()返回的值有時比實際答案少1。

int main() 
{ 
std::cout<<"11!:"<<tgamma(12)<<std::endl; 
std::cout<<"12!"<<tgamma(13)<<std::endl; 
std::cout<<"13!"<<tgamma(14)<<std::endl; 
std::cout<<"14!"<<tgamma(15)<<std::endl; 
std::cout<<"15!"<<tgamma(16)<<std::endl; 
std::cout<<"16!"<<tgamma(17)<<std::endl; 
std::cout<<"********************************"<<std::endl; 
std::cout<<"11!:"<<(long long)tgamma(12)<<std::endl; 
std::cout<<"12!"<<(long long)tgamma(13)<<std::endl; 
std::cout<<"13!"<<(long long)tgamma(14)<<std::endl; 
std::cout<<"14!"<<(long long)tgamma(15)<<std::endl; 
std::cout<<"15!"<<(long long)tgamma(16)<<std::endl; 
std::cout<<"16!"<<(long long)tgamma(17)<<std::endl; 
return 0; 
} 

我得到以下輸出:

11!:3.99168e+07 
12!4.79002e+08 
13!6.22702e+09 
14!8.71783e+10 
15!1.30767e+12 
16!2.09228e+13 
******************************** 
11!:39916800 
12!479001599 
13!6227020799 
14!87178291199 
15!1307674367999 
16!20922789888000 

的15實際值!根據this site是1307674368000但是當我tymatast tgamma(16)很長的時間,我只得到1307674367999。事情是這種差異只出現了一些數字。 16型的答案!是正確的 - 20922789888000.

此功能是針對目前正在進行的競爭性編程問題,所以我無法將功能和我正在開發的解決方案粘貼到此處。

我會推出自己的因子函數,但我想減少我的程序中的字符數以獲得積分。

有關如何檢測這種類型值的差異並糾正它的任何提示?或者,也許我可以使用一些其他功能?

+0

tgamma與浮點數一起工作,這可能會失去精度。爲什麼不使用整數編寫自己的因子函數? – jtbandes

+0

「tgamma()函數本身以科學記數法返回正確的值。」 - 不,它不。 C++有一個乾淨的設計。該值作爲二進制值返回。科學記數法是一種文本格式,可以在將二進制值轉換爲文本時應用。 – MSalters

回答

0

從浮點類型轉換爲整型截斷。嘗試(long long) roundl(tgammal(xxx))以消除整數截斷錯誤。這也是使用長雙打,所以它可能會給你更多的數字。

#include <math.h> 
#include <iostream> 
int main(){ 
    std::cout<<"11!:"<<(long long)roundl(tgammal(12))<<std::endl; 
    std::cout<<"12!"<<(long long)roundl(tgammal(13))<<std::endl; 
    std::cout<<"13!"<<(long long)roundl(tgammal(14))<<std::endl; 
    std::cout<<"14!"<<(long long)roundl(tgammal(15))<<std::endl; 
    std::cout<<"15!"<<(long long)roundl(tgammal(16))<<std::endl; 
    std::cout<<"16!"<<(long long)roundl(tgammal(17))<<std::endl; 
    std::cout<<"********************************"<<std::endl; 
    std::cout<<"11!:"<<(long long)roundl(tgammal(12))<<std::endl; 
    std::cout<<"12!"<<(long long)roundl(tgammal(13))<<std::endl; 
    std::cout<<"13!"<<(long long)roundl(tgammal(14))<<std::endl; 
    std::cout<<"14!"<<(long long)roundl(tgammal(15))<<std::endl; 
    std::cout<<"15!"<<(long long)roundl(tgammal(16))<<std::endl; 
    std::cout<<"16!"<<(long long)roundl(tgammal(17))<<std::endl; 
    return 0; 
} 

給出:

11!:39916800 
12!479001600 
13!6227020800 
14!87178291200 
15!1307674368000 
16!20922789888000 
******************************** 
11!:39916800 
12!479001600 
13!6227020800 
14!87178291200 
15!1307674368000 
16!20922789888000 
+0

這幫了我。謝謝! –

+0

爲什麼這個錯誤只出現在一些數字上?如果它是一個錯誤,它不應該是統一的嗎?爲什麼只有15!在16歲時,類型錯誤的答案是錯誤的!答案不是? –

+1

tgamma是近似值。投射到整數類型截斷而不是輪。使用更多數字和round/roundl將有助於兩者。 – evaitl

0

很明顯,除非我們有極不尋常的實施,並非所有的很長很長的數字可以準確地表示爲雙。因此,tgamma不能存儲雙倍值,以致長時間投射會產生精確值。在很長的時間間隔內,只有更長的long值比double值更長。

如果你想確切的長期因子,你應該自己實現它。 (long long)x,或(long long)round(x),或(long long)(x + 0.5),將double轉換爲long long並不是long long long,假設x是正數。

+0

不錯的解釋! (long long)(tgamma(x)+ 0.5)會產生較短的代碼...很好的提示! –

+0

是否有任何標準的C++函數可以返回數字的確切階乘,而無需執行此類類型轉換錯誤解決方法? –

+0

Google for'std factorial standard library',你會找到答案:) – user31264