2012-06-24 92 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π,那么结果在数学上会有所不同:我怀疑有些超验数字。