我试图用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
感谢您的答复,但我需要一个更精确的数字。 –