斐波那契's递归关系在大数上的精度损失
本文关键字:损失 精度 关系 递归 | 更新日期: 2023-09-27 18:19:24
我正在尝试使用Binet的公式来解决斐波那契的n数字与 0 (1)时间复杂度。
class Application
{
static void Main(string[] c)
{
Console.WriteLine($"Fib(15) : Expected 610 got : {Fibonacci(15)}");
Console.WriteLine($"Fib(20) : Expected 6765 got : {Fibonacci(20)}");
Console.WriteLine($"Fib(100) : Expected 354224848179261915075 got : {Fibonacci(100)}");
Console.ReadKey();
}
private static BigInteger Fibonacci(int n)
{
double sqrt5 = Math.Sqrt(5d);
return new BigInteger((1/sqrt5)*Math.Pow((1 + sqrt5)/2, n) - (1/sqrt5)*Math.Pow((1 - sqrt5)/2, n));
}
}
下面的例子在前两个测试中非常成功,但在第三个测试中却失败了很多(结果是354224848179263111168
vs. 354224848179261915075
。
我猜这可能是我的公式的Math.Pow((1+sqrt5)/2,n)
部分的问题,但我尝试使用公式使用decimal
, double
, float
和BigInteger
本身,结果从来都不是好的一个。
是否有办法解决我的问题,或者我应该接受我不能使用Math.Pow
做到这一点?
编辑我尝试使用BigInteger.Pow
,但要使用它1+sqrt5
也需要是BigInteger
,这使得我的代码看起来像这样在结束时,因为cast:
double sqrt5 = Math.Sqrt(5d);
return new BigInteger(1/sqrt5)*BigInteger.Pow(new BigInteger(1 + sqrt5/2), n) - new BigInteger(1 / sqrt5) * BigInteger.Pow(new BigInteger((1 - sqrt5)/2), n);
使用double总是有15位半的精度。你不能期望更多,整数转换的输出只能和输入一样好。
这就是为什么对于n位计算,即使是binet公式也不是O(1)而是O(M(n)),使用F[n]小于2^n,其中M(n)是乘法的代价,这也是指数和对数的代价的度量。