如何在C#中将BigInteger转换为pow Double?
我尝试使用如何在C#中将BigInteger转换为pow Double?,c#,math,biginteger,C#,Math,Biginteger,我尝试使用biginger.Pow方法来计算10^12345.987654321之类的值,但此方法仅接受整数作为指数,如下所示: Pow(大整数x,整数y) 那么,如何在上述方法中使用双倍数作为指数?在C#中不支持任意精度的大数,因此无法直接实现。有一些替代方案(比如寻找第三方库),或者您可以尝试下面的代码——如果库足够小,比如您的情况 public class StackOverflow_11179289 { public static void Test() {
biginger.Pow
方法来计算10^12345.987654321之类的值,但此方法仅接受整数作为指数,如下所示:
Pow(大整数x,整数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);
}
}
我们可以将这两个值合并成一个大整数。但是简单地将double值转换为BigInteger会损失很多精度,因此我们首先将精度“移位”到BigInteger上(使用上面的循环,以及double
类型使用52位精度的事实),然后将结果相乘
请注意,结果是近似值,如果需要更精确的数字,则需要一个执行任意精度浮点运算的库
更新:如果基/指数足够小,幂在
double
的范围内,我们可以简单地按照塞巴斯蒂安·皮尤的建议(新的大整数(Math.Pow((double)@base,exp))
)我喜欢卡洛斯·菲盖拉的答案,但当然他的方法的结果只能在第一步是正确的(最高有效)15-17位,因为系统.Double
最终用作乘法器
值得注意的是,确实存在一种执行“逆”运算的方法biginger.Log
。因此,如果您想计算Pow(7123456.78)
理论上,您可以搜索所有biginger
numbersx
以找到一个biginger.Log(x,7)的数字
等于123456.78
或比biginger
类型的任何其他x
更接近123456.78
当然,对数函数在增加,因此您的搜索可以使用某种“二进制搜索”(对分搜索)。我们的答案介于Pow(7123456)
和Pow(7123457)
之间,两者都可以精确计算
如果需要,请跳过其余部分
现在,我们如何提前预测是否有一个以上的整数的对数是123456.78
,达到System.Double
的精度,或者实际上没有一个整数的对数达到特定的Double
(理想的Pow
函数的精确结果是无理数)?在我们的示例中,会有很多整数给出相同的Double
123456.78
,因为因子m=Pow(7,ε)
(其中,epsilon
是最小的正数,123456.78+epilon
表示为Double
,不同于123456.78
本身的表示)足够大,以至于真实答案和真实答案乘以m
之间会有很多整数
从微积分中记住,数学函数的导数x→ 功率(7,x)
isx→ Log(7)*Pow(7,x)
,因此所讨论的指数函数图的斜率将是Log(7)*Pow(7123456.78)
。这个数字乘以上面的epsilon
仍然远远大于1,因此有许多整数满足了我们的需要
实际上,我认为carlosfigueira的方法将给出一个“正确”的答案
x
,即Log(x,7)
与123456.78
具有相同的Double
表示。但是有人尝试过吗?:-)我将提供另一个希望更清楚的答案。重点是:因为系统的精度。Double
被限制为大约15-17位小数,这是任何Pow(biginger,Double)的结果
计算的精度将更加有限。因此,没有希望比carlosfigueira的答案做得更好
让我用一个例子来说明这一点。假设我们想要计算
Pow(10, exponent)
在本例中,我选择双精度数字作为指数
const double exponent = 100.0 * Math.PI;
这当然只是一个例子。指数
(十进制)的值可以作为
314.159265358979
314.15926535897933
314.1592653589793258106510620564222335815429687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
这些数字中的第一个是您通常看到的数字(15位)。第二个版本是使用exponent.ToString(“R”)生成的,包含17位数字。请注意,Double
的精度小于17位。上面的第三个表示是理论上的“精确”指数的值
。请注意,这当然与第17位附近的数学数字100π不同
为了弄清楚Pow(10,指数)应该是什么,我简单地对许多数字x
进行了biginger.Log10(x)
,以了解如何重现index
。因此,这里给出的结果只是反映了.NET框架对biginger.Log10
的实现
结果是,任何biginger x
都来自
0x0C3F859904635FC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
through
0x0C3F85990481FE7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
使Log10(x)
等于指数
,精度为15位。类似地,从
0x0C3F8599047BDEC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
through
0x0C3F8599047D667FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
满足Log10(x)=指数
到Double
的精度。换句话说,后一个范围内的任何数字作为Pow(10,指数)
的结果都是同样“正确”的,因为指数
的精度非常有限
(插曲:0
s和F
s表明.NET的实现只考虑了x
中最重要的字节。他们不想做得更好,正是因为Double
类型的精度有限。)
现在,引入第三方的唯一原因
0x0C3F8599047BDEC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
through
0x0C3F8599047D667FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF