2013-08-20 83 views
3

我很難弄清楚如何處理我遇到的問題。 作爲一個複雜公式的一部分,我需要計算一個可以快速溢出兩倍的部分,即結果達到〜1.59 * 10 ^(1331)(用mathematica計算)。 當然這超出了雙倍的範圍。然後我想用long double,在我的linux系統上用gcc 4.6.3是16byte。使用GMP從公式計算非常大的整數

1)雙精度(8字節)的可能範圍可達10 ^(308)。我是否正確地說,長雙重然後增加實際精確度,但不是值的可能數字範圍?我記得我聽說它可以是或者,取決於系統和編譯器。真的嗎 ?至少我仍然拿到NaN,當我嘗試用長雙倍來計算我的數值時。

2.)當時我正在尋找一種方法來實際計算這些結果,並且我找到了GNU gmp。我聽說你可以代表非常大的整數,我認爲這可能有幫助。然而,閱讀文檔,似乎與

mpz_t x; 
mpz_init(x); 
mpz_set_*(x,#); 

我可以賦值gmp整數數據類型,但爲了做到這一點,我可以「唯一」選擇指派通過內置表示的值像double或(u/s)int等數據類型。所有我發現如何分配真正巨大的數字是使用mpz_set_str()來分配字符串中的數字。 我該如何分配一個複雜計算結果的數字? 簡單地說,公式是這樣的:

long double res1,res2=0.0; 
int a,b; 
a=780; 
b=741; 
float d,d1,o,s; // can be values in [0.01,100] 

res1=(2*(pow(b,2)*pow(E,b*(o + s))*(pow(d1,2) + pow(E,a*s)*(-1 + pow(E,a*o)) + pow(d,2)*(-1 + pow(E,a*s))) + pow(a,2)*pow(E,a*(o + s))*(pow(E,b*s)*(pow(E,b*o) + (-1 + d)*(1 + d + b*o)) + (-d + d1)*(d + d1 + b*o + b*d*s)) - a*b*(pow(d1,2)*(pow(E,a*(o + s)) + pow(E,b*(o + s))) + pow(E,a*o + (a + b)*s)*(-2 + 2*pow(E,b*o) - b*o) + d1*pow(E,a*s)*(-pow(E,b*o) + pow(E,a*o)*(1 + b*o)) + pow(d,2)*pow(E,a*s)*(-pow(E,b*o) + pow(E,b*(o + s)) + pow(E,a*o)*(-1 + pow(E,b*s) - b*s)) + d*(-(d1*pow(E,b*(o + s))) + (1 + d1)*pow(E,b*o + a*s) - pow(E,a*s + b*(o + s)) + pow(E,b*s + a*(o + s))*(1 + b*o) + pow(E,a*(o + s))*(-1 - b*o + b*d1*s)))))......; 

RES2也將是這樣的,而且我到底需要計算RES1/RES2,這通常成爲一個非常小的數目。

我在考慮將公式拆分並向mpg_z添加條件以避免每個術語超出雙倍範圍,但由於公式太長且複雜,因此幾乎不可能。

因此,總之,問題是,我的中間結果會變得如此之大以至於沒有數據類型能夠存儲它們,所以我不能將它分配給mpz並擺脫此問題。

我知道我想計算一個double值,並且實際使用整數mpz_t。據我所知,這是存儲這種大數據的唯一方法,因爲mpf_t只能處理float類型。說實話,我的身邊仍然有關於gmp中的表示的混淆。

任何想法如何解決這個問題?

+0

考慮使用所有mpz_t變量。丟失整數變量(在我看到的代碼部分中被提升爲雙精度),無論如何你都無法獲得任何東西。從你的函數的一開始就做一切mpz_t。順便說一句你想做什麼? –

+1

它看起來像你沒有做整數算術,所以我會堅持使用mpf_t並使用gmp提供的浮點運算來實現整個公式。 – mwv

+0

這是理論種羣遺傳學,我試圖計算給定任意人口統計分段函數的內胚乳時間的瞬間 – user1841373

回答

1

問題1 Long double允許處理比double更大的數字(包括指數和有效數字的精度)。但是你必須認爲,如果你的目標是存儲大整數,你的1e308數量級並不意味着什麼;您只需關心有效位精度的大小,即52/53位(雙精度)或64位(x86精度)。如果你試圖用更大的整數來使用它,你將會得到一個正確的數量級,但是確切的數值將會丟失(當用整數進行計算時,人們通常比使用近似數字時更關心這一點)。

問題2使用GMP是一個不錯的選擇。其他圖書館也存在;對於較小的值,我使用了很多libqd,它具有擴展的固定精度,並且非常快速但這對於您自己的問題還不夠。現在你的問題是關於設置值:

  • 使用字符串版本的數字通常是一個壞主意(你應該保持,只爲輸入/輸出的目的);它是由數字處理
  • 做盡可能多的,你可以用GMP類型涉及基礎轉換和數字一個緩慢的操作去(除非你真的關心速度,並有超預期的範圍值的完全控制的方式與本機類型來計算
  • 如果公式是太長了,我不能幫助很多,但是使用GMP並不難,你能不能真正轉換公式?有沒有在公式中的一些邏輯,你可以在一個循環中嵌入?也許你可以寫一個快速和骯髒的Python腳本爲您的公式轉換爲使用GMP一塊C代碼?

現在我不完全理解爲什麼要使用mpz_t而不是mpf_t。這種類型實現了任意長的浮點數;你注意到你可以使用mpf_set_default_prec來設置精度嗎?