Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 4.0 计算斐波那契_C# 4.0_Fibonacci - Fatal编程技术网

C# 4.0 计算斐波那契

C# 4.0 计算斐波那契,c#-4.0,fibonacci,C# 4.0,Fibonacci,我收到了一个很好的非递归函数,用于计算斐波那契序列 所以我编了一点c#,并且能够验证1474之前的所有数字都是正确的 当试图计算1475及更高版本时,出现了问题。我的c#math技能无法胜任找出另一种方法的任务。那么,有人有更好的方法用c#来表达这个特殊的数学函数吗?除了执行递归函数的传统方法之外 顺便说一句,我开始使用BigInteger作为返回类型。但是当试图将(1+Math.Sqrt(5)/2)提高到1475次方时,问题就出现了。我只是不知道我需要什么样的数据类型(也不知道是什么机制)来

我收到了一个很好的非递归函数,用于计算斐波那契序列

所以我编了一点c#,并且能够验证1474之前的所有数字都是正确的

当试图计算1475及更高版本时,出现了问题。我的c#math技能无法胜任找出另一种方法的任务。那么,有人有更好的方法用c#来表达这个特殊的数学函数吗?除了执行递归函数的传统方法之外

顺便说一句,我开始使用BigInteger作为返回类型。但是当试图将(1+Math.Sqrt(5)/2)提高到1475次方时,问题就出现了。我只是不知道我需要什么样的数据类型(也不知道是什么机制)来让它返回到无穷大之外的东西

这是一个起点

private Double FibSequence(Int32 input) {
    Double part1 = (1 / Math.Sqrt(5));
    Double part2 = Math.Pow(((1 + Math.Sqrt(5)) / 2), input);
    Double part3 = Math.Pow(((1 - Math.Sqrt(5)) / 2), input);

    return (part1 * part2) - (part1 * part3);
}

而且,不,这不是家庭作业。这只是一个“简单”的慢日问题。

双精度数据类型的上限为1.7 x 10^308

1474的计算包括一步~1.1 x 10^308的值

所以,到1475年,你肯定超过了双精度所能代表的。不幸的是,C#唯一较大的原语Decimal(128位数字)被设计为具有非常高的进动,但范围相对较小(仅高达10^28左右)

如果没有设计一种自定义数据类型,它可以处理大于10^308的数字,并具有一定的十进制精度,我看不出有什么方法可以做到这一点。这就是说,可能有人已经做了这样一个类,因为我可以想象它可能会派上用场的场景

见双页:

和十进制:

问题是(5^(1/2)^1475)很容易溢出int。您需要做的是编写一个“大数学”库来处理从内存(逐位)进行数学运算,而不是使用硬类型的数据类型。这是一种痛苦,但是,我知道。查找平方和乘法方法。

我认为C#的数据类型没有足够的浮点精度和范围来处理这个问题

如果你真的想沿着这条路走下去,你可以注意到共轭小于1,这与舍入到最接近的整数一样,因此你可以简化你的求解。然后使用二项式展开,这样您只需使用适当的a和b(它们是有理的,可以使用BigInteger精确计算)进行计算。如果你仍然返回到Double,你仍然不会得到比1475更多的东西,但是你应该能够找出如何用精确的整数数学来完成这部分☺



还有另一种计算斐波那契数的简洁方法,使用矩阵求幂法:

如果你聪明的话,这可以在O(logn)中完成


我最终在Haskell中实现了这些
fib1
是矩阵求幂,
fib2
是闭式公式的精确整数转换,如上所述。它们各自的运行时如下所示,由编译时的度量:

导入控件。箭头
导入数据。列表
导入数据。比率
新类型Matrix2 a=Matrix2(a,a,a,a)派生(显示,等式)
实例(Num a)=>Num(Matrix2 a),其中
矩阵2(a,b,c,d)*矩阵2(e,f,g,h)=
矩阵2(a*e+b*g,a*f+b*h,c*e+d*g,c*f+d*h)
fromInteger x=设y=矩阵X2中的fromInteger x(y,0,0,y)
fib1 n=设矩阵2(x,x,x,x)=矩阵2(1,1,1,0)^n在x中
比诺姆=
scanl(\a(b,c)->a*b`div`c)1$
takeWhile((/=)0.fst)$iterate(pred***succ)(n,1)
evens(x:ux:xs)=x:evens-xs
evens xs=xs
赔率(uux:xs)=x:赔率xs
赔率
迭代'f x=x:(迭代'f$!f x)
幂b=迭代(b*)1
esqrt e n=x,其中
(ux):x=dropWhile((x+n/x)/2)n
fib'n=(a,b)其中
d=2^n
a=总和(zipWith(*)(赔率$binom n)(幂5))%d
b=总和(zipWith(*)(偶数$binom n)(幂5))%d
fib2 n=分子r`div`分母r,其中
(a,b)=fib'n
l=lcm(分母a)(分母a)
r=a+esqrt(1%最大3升)(b*b/5)+1%2

正如您正确指出的,没有为BigInteger实现Sqrt方法。 不过,您可以自己实现它:


但是,您的代码仍然存在精度问题。

这里的许多答案表明,复杂性可以最小化到O(log(n))。为什么不尝试log(n)方法的整数实现呢

首先,从FiBaaCKi的序列中考虑两个术语:<代码> f(n)< /代码>和<代码> f(n+1)< /代码>。它的逻辑是:较大的术语<代码> f(n+k)< /代码>可以被写为<代码> f(n)< /代码>和<代码> f(n+1)< /代码>为

 F(n+k) = Ck1*F(n) + Ck2*F(n+1)
您可以只计算这些系数(仅取决于
k
)(有趣的是,它们也是斐波那契序列!)并使用它们来加快推进速度,然后再次计算它们以获得更大的
k
值,从而能够加快推进速度,以此类推。

似乎包括一些“大”数字类型。它的
Rational
类型可能为您提供所需的精度和范围。它表示有理数为2的比率
biginger
值。(它自带了自己的
biginger
——我想它是在.NET4发布之前编写的。)

从理论上讲,这使它能够表示非常大的数字,但也可以表示非常高的精度。(显然,您的公式不处理有理数,但浮点也是一个近似值。)

它提供了一种方法,将一个
Rational
提升到其他事物的力量:

最快(和最脏)?:D

专用双脏数学函数(Int32输入){
双部分1=(1/Math.Sqrt(5));
双部件2=数学功率((1+数学Sqrt(5))/2),输入;
Double part3=Math.Pow((1-Math.Sqrt(5))/2),输入;
退货(第1部分*第2部分)-(第1部分*第3部分);
}
专用双FibSequence(Int32输入){
如果(输入<1
 F(n+k) = Ck1*F(n) + Ck2*F(n+1)
private Double dirty_math_function(Int32 input){
       Double part1 = (1 / Math.Sqrt(5));
       Double part2 = Math.Pow(((1 + Math.Sqrt(5)) / 2), input);
       Double part3 = Math.Pow(((1 - Math.Sqrt(5)) / 2), input);
       return (part1 * part2) - (part1 * part3);
 }

private Double FibSequence(Int32 input) {
  if(input < 1475)
       return dirty_math_function(input);
  else{
       return (FibSequence(input -1) + FibSequence(intput -2));
  }
}
using System;
using Nat = System.Numerics.BigInteger; // needs a reference to System.Numerics

class Program
{
    static void Main()
    {
        Console.WriteLine(Fibonacci(1000));
    }

    static Nat Fibonacci(Nat n)
    {
        if (n == 0) return 0;
        Nat _, fibonacci = MatrixPower(1, 1, 1, 0, Nat.Abs(n) - 1, out _, out _, out _);
        return n < 0 && n.IsEven ? -fibonacci : fibonacci;
    }

    /// <summary>Calculates matrix power B = A^n of a 2x2 matrix.</summary>
    /// <returns>b11</returns>
    static Nat MatrixPower(
        Nat a11, Nat a12, Nat a21, Nat a22, Nat n,
        out Nat b12, out Nat b21, out Nat b22)
    {
        if (n == 0)
        {
            b12 = b21 = 0; return b22 = 1;
        }

        Nat c12, c21, c22, c11 = MatrixPower(
            a11, a12, a21, a22,
            n.IsEven ? n / 2 : n - 1,
            out c12, out c21, out c22);

        if (n.IsEven)
        {
            a11 = c11; a12 = c12; a21 = c21; a22 = c22;
        }

        b12 = c11 * a12 + c12 * a22;
        b21 = c21 * a11 + c22 * a21;
        b22 = c21 * a12 + c22 * a22;
        return c11 * a11 + c12 * a21;
    }
}