我試圖用BigInteger.Pow
方法來計算像10^12345.987654321但這種方法只接受整數作爲這樣指數:如何將BigInteger轉換爲C#中的pow double?
BigInteger.Pow(的BigInteger的x,int y)對
所以如何在上述方法中使用雙數作爲指數?
我試圖用BigInteger.Pow
方法來計算像10^12345.987654321但這種方法只接受整數作爲這樣指數:如何將BigInteger轉換爲C#中的pow double?
BigInteger.Pow(的BigInteger的x,int y)對
所以如何在上述方法中使用雙數作爲指數?
在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))
)
我喜歡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
函數的精確結果是一個無理數)?在我們的例子中,會有非常多的整數給予同樣的Double
123456.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)
具有相同的表示爲Double
爲123456.78
了。但有沒有人嘗試過? :-)
我會提供另一個有希望更清楚的答案。關鍵是:由於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π,那麼結果在數學上會有所不同:我懷疑有些超驗數字。
我只是出於好奇而問,爲什麼不做新的'new BigInteger(Math.Pow(10,123.123));'正確嗎? –
他想做10^** 12345.123 **,這會超出double的範圍(Math.Pow的結果)。我減少了它,所以我可以在我的控制檯應用程序中看到結果,但我會再次增加它以清楚。 – carlosfigueira
感謝您的答覆,但我需要一個更精確的數字。 –