2012-06-24 96 views

回答

5

在C#中沒有任何精確的大數目支持,所以這不能直接完成。有一些選擇(如尋找第三方庫),或者你可以嘗試像下面的代碼 - 如果基地足夠小,就像你的情況。

public class StackOverflow_11179289 
{ 
    public static void Test() 
    { 
     int @base = 10; 
     double exp = 12345.123; 
     int intExp = (int)Math.Floor(exp); 
     double fracExp = exp - intExp; 
     BigInteger temp = BigInteger.Pow(@base, intExp); 
     double temp2 = Math.Pow(@base, fracExp); 
     int fractionBitsForDouble = 52; 
     for (int i = 0; i < fractionBitsForDouble; i++) 
     { 
      temp = BigInteger.Divide(temp, 2); 
      temp2 *= 2; 
     } 

     BigInteger result = BigInteger.Multiply(temp, (BigInteger)temp2); 

     Console.WriteLine(result); 
    } 
} 

的想法是使用大整數運算來計算指數的整數部分的電源,然後使用雙(64位浮點)數學計算分數部分的功率。然後,使用事實

a^(int + frac) = a^int * a^frac 

我們可以將這兩個值組合成一個大的整數。但是簡單地將double值轉換爲BigInteger將會失去很多精度,所以我們首先將精度轉移到bigInteger上(使用上面的循環,以及double類型使用52位精度),然後乘以結果。

請注意,結果是一個近似值,如果您想要一個更精確的數字,您需要一個執行任意精度浮點數學運算的庫。

更新:如果基/指數足夠小,功率將在double的範圍內,我們可以簡單地做塞巴斯蒂安彪建議(new BigInteger(Math.Pow((double)@base, exp))

+0

我只是出於好奇而問,爲什麼不做新的'new BigInteger(Math.Pow(10,123.123));'正確嗎? –

+2

他想做10^** 12345.123 **,這會超出double的範圍(Math.Pow的結果)。我減少了它,所以我可以在我的控制檯應用程序中看到結果,但我會再次增加它以清楚。 – carlosfigueira

+0

感謝您的答覆,但我需要一個更精確的數字。 –

2

我喜歡carlosfigueira的答案,但當然他的方法的結果只能在第一個(最重要的)15-17位數字上正確,因爲最終將System.Double用作乘數。

值得注意的是,確實存在執行「反轉」操作的方法BigInteger.Log。所以,如果你想計算Pow(7, 123456.78)你可以在理論上,搜索所有BigInteger數字x找到一個數,使得BigInteger.Log(x, 7)等於123456.78或超過BigInteger類型的任何其他x接近123456.78

當然,對數函數正在增加,所以你的搜索可以使用某種「二分搜索」(二分搜索)。我們的答案在Pow(7, 123456)Pow(7, 123457)之間,它們都可以精確計算。

跳過剩下的,如果你想

現在,我們怎樣才能提前預知,如果有一個以上的整數,其對數爲123456.78,高達System.Double精度,或者如果沒有事實整數的對數是否符合特定的Double(理想的Pow函數的精確結果是一個無理數)?在我們的例子中,會有非常多的整數給予同樣的Double123456.78,因爲因素m = Pow(7, epsilon)(其中epsilon是最小的正數,使得123456.78 + epilon有一個表示爲從123456.78本身代表不同Double)足夠大,將有在真實答案和真實答案之間乘以m是非常多的整數。

請記住微積分函數x → Pow(7, x)的導數爲x → Log(7)*Pow(7, x),所以所討論的指數函數圖的斜率將爲Log(7)*Pow(7, 123456.78)。這個數字乘以上面的epsilon仍然遠遠大於1,所以有很多整數滿足我們的需要。

其實我覺得carlosfigueira的方法會給出一個「正確」的答案x在這個意義上,Log(x, 7)具有相同的表示爲Double123456.78了。但有沒有人嘗試過? :-)

1

我會提供另一個有希望更清楚的答案。關鍵是:由於System.Double的精度限制在約。 15-17位十進制數字,任何Pow(BigInteger, Double)計算的結果將具有更精確的限制。因此,沒有比carlosfigueira的答案做得更好的希望。

讓我用一個例子來說明這一點。假設我們要計算

Pow(10, exponent) 

凡在這個例子中我選擇exponent雙精度數

const double exponent = 100.0 * Math.PI; 

這當然只是一個例子。的exponent值,十進制,可以作爲的

314.159265358979 
314.15926535897933 
314.1592653589793258106510620564222335815429687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000... 

第一個號碼是什麼,你通常會看到(15位)。第二版由exponent.ToString("R")生成,包含17位數字。請注意,Double的精度小於17位數。上面的第三個表示是exponent的理論「確切」值。請注意,這與第17位附近的數學數字100π不同。

找出Pow(10, exponent)應該是,我壓根兒BigInteger.Log10(x)上很多數字x的,看我怎麼能複製exponent。所以這裏給出的結果僅僅反映了.NET框架的實現BigInteger.Log10

事實證明,任何BigInteger x

0x0C3F859904635FC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 
through 
0x0C3F85990481FE7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 

使得Log10(x)等於exponent到的15位的精度。類似地,任何數量的從

0x0C3F8599047BDEC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 
through 
0x0C3F8599047D667FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 

滿足Log10(x) == exponent到的Double精度。換言之,任何號碼與後者的範圍相同,因爲Pow(10, exponent)的結果是同樣「正確的」,僅僅是因爲exponent的精度如此有限。

(插曲:。的0 S和F S中的串表明.NET的實現僅考慮x最顯著字節他們不在乎做的更好,正是因爲Double類型有這個有限的精度)

現在,引進第三方軟件的唯一原因,是,如果你堅持exponent是被解釋爲第三上面給出的十進制數。 (Double類型允許你準確指定你想要的數字真的是個奇蹟,呵呵?)在這種情況下,Pow(10, exponent)的結果將是一個非理性(但是代數)的數字,並且有一個不重複小數的尾部。如果沒有四捨五入/截斷,它無法放入一個整數。 PS!如果我們將指數作爲實數100π,那麼結果在數學上會有所不同:我懷疑有些超驗數字。