Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.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#十进制精度在幂和斐波那契中的改进_C#_Precision_Fibonacci - Fatal编程技术网

C#十进制精度在幂和斐波那契中的改进

C#十进制精度在幂和斐波那契中的改进,c#,precision,fibonacci,C#,Precision,Fibonacci,我试图用负数和大数来解斐波那契序列,并提出了以下代码和算法。我确信算法是可行的,但我面临的问题是,对于非常大的数字,结果的精度是不正确的。代码如下: public class Fibonacci { public static BigInteger fib(int n) { decimal p = (decimal) (1 + Math.Sqrt(5)) / 2; decimal q = (decimal)

我试图用负数和大数来解斐波那契序列,并提出了以下代码和算法。我确信算法是可行的,但我面临的问题是,对于非常大的数字,结果的精度是不正确的。代码如下:

public class Fibonacci
    {
        public static BigInteger fib(int n)
        {
            decimal p = (decimal) (1 + Math.Sqrt(5)) / 2;
            decimal q = (decimal) (1 - Math.Sqrt(5)) / 2;
            decimal r = (decimal) Math.Sqrt(5);
            Console.WriteLine("n: {0} p: {1}, q: {2}, t: {3}",
              n,
              p,
              q,
              (Pow(p, n) - Pow(q, n)) / r);

            return (BigInteger) (Decimal.Round((Pow(p, n) - Pow(q, n)) / r));
        }

        public static decimal Pow(decimal x, int y)
        {
            if(y < 0)
                return 1 / Pow(x, -1 * y);
            else if(y == 0)
                return 1;
            else if(y % 2 == 0)
            {
                decimal z = Pow(x, y / 2);
                return z * z;
            }
            else if(y % 2 == 1)
                return Pow(x, y - 1) * x;
            else
                return 1;
        }
公共类Fibonacci
{
公共静态大整数fib(int n)
{
十进制p=(十进制)(1+数学Sqrt(5))/2;
十进制q=(十进制)(1-数学Sqrt(5))/2;
十进制r=(十进制)数学Sqrt(5);
WriteLine(“n:{0}p:{1},q:{2},t:{3}”,
N
P
Q
(Pow(p,n)-Pow(q,n))/r;
返回(BigInteger)(十进制整数((Pow(p,n)-Pow(q,n))/r));
}
公共静态十进制功率(十进制x,整数y)
{
if(y<0)
返回1/Pow(x,-1*y);
如果(y==0),则为else
返回1;
如果(y%2==0),则为else
{
十进制z=功率(x,y/2);
返回z*z;
}
如果(y%2==1),则为else
返回功率(x,y-1)*x;
其他的
返回1;
}
如果我们取一个像-96这样的大数字来得到斐波那契函数,我得到的结果是-516807085733203484173,但实数是-5168070854858323072。我检查了舍入是否正确,但我的结果似乎在某个地方失去了精度,无法正确保存它的值。我认为使用小数可以解决这个问题ision问题(以前使用双倍),但这不起作用

在我的代码中,哪里错误地丢失了精度,或者我的代码中有另一个问题被误诊了?

试试这个

public static BigInteger Fibonacci(int n)
    {
        BigInteger a = 0;
        BigInteger b = 1;
        for (int i = 31; i >= 0; i--)
        {
            BigInteger d = a * (b * 2 - a);
            BigInteger e = a * a + b * b;
            a = d;
            b = e;
            if ((((uint)n >> i) & 1) != 0)
            {
                BigInteger c = a + b;
                a = b;
                b = c;
            }
        }
        return a;
    }
祝你好运!试试这个

public static BigInteger Fibonacci(int n)
    {
        BigInteger a = 0;
        BigInteger b = 1;
        for (int i = 31; i >= 0; i--)
        {
            BigInteger d = a * (b * 2 - a);
            BigInteger e = a * a + b * b;
            a = d;
            b = e;
            if ((((uint)n >> i) & 1) != 0)
            {
                BigInteger c = a + b;
                a = b;
                b = c;
            }
        }
        return a;
    }

祝你好运!

正如你所写的,
十进制
大约有28位小数精度。但是,
Math.Sqrt(5)
,作为
双精度
,却没有

使用更精确的平方根5可以使该算法在更长的时间内保持精确,当然它最终还是会受到精度的限制,就在稍后

public static BigInteger fib(int n)
{
    decimal sqrt5 = 2.236067977499789696409173668731276235440618359611525724270m;
    decimal p = (1 + sqrt5) / 2;
    decimal q = (1 - sqrt5) / 2;
    decimal r = sqrt5;

    return (BigInteger) (Decimal.Round((Pow(p, n) - Pow(q, n)) / r));
}

这样一来,
fib(96)=5168070854858323072是正确的。但是,它在128处再次出错。

正如您所写,
decimal
大约有28位小数精度。但是,
Math.Sqrt(5)
作为
双精度
,却没有

使用更精确的平方根5可以使该算法在更长的时间内保持精确,当然它最终还是会受到精度的限制,就在稍后

public static BigInteger fib(int n)
{
    decimal sqrt5 = 2.236067977499789696409173668731276235440618359611525724270m;
    decimal p = (1 + sqrt5) / 2;
    decimal q = (1 - sqrt5) / 2;
    decimal r = sqrt5;

    return (BigInteger) (Decimal.Round((Pow(p, n) - Pow(q, n)) / r));
}


这样
fib(96)=5168070854858323072
这是正确的。但是,它在128处再次出错。

将十进制更改为大整数不会神奇地提高十进制的分辨率。@AndrewMorton我理解这一点,但根据文档,十进制类型应具有28到29位精度。输出需要大整数这就是为什么我要进行十进制.四舍五入。但是,该值的精度几乎在10到15位之间,因此有些地方不准确。您是否检查过中间值的精度,例如
Pow(p,n)
?@AndrewMorton正在检查。我可以验证算法无法处理超过第68个值的fibonacci数。将十进制更改为BigInteger不会神奇地提高十进制的分辨率。@AndrewMorton我理解,但根据文档,十进制类型的精度应为28到29位。BigIn输出需要teger,这就是为什么我要进行decimal.round。但是,该值在几乎10到15位的范围内失去精度,所以有些地方不对劲。您是否检查了中间值的准确性,例如
Pow(p,n)
?@AndrewMorton正在检查。我可以验证该算法无法处理超过第68个值的斐波那契数。是的,这是求解斐波那契序列的一种非常标准的方法。但是,这不够快,需要不到几秒钟的时间,而不是几分钟的时间。而且,这个答案也没有回答我关于精度的问题。@RossGustafson我认为你应该检查这种方法的性能,它不应该花费几分钟。这不是简单的“添加最后两个值”方法。这种方法只有32次迭代。我尝试过斐波那契(96)结果:结果:5168070854858323072,经过时间:00:00:00.0020192。您期望的精度值是多少?这会中断负斐波那契数。我一开始误解了您的解决方案。我知道它在做什么。有趣的解决方案。是的,这是解决斐波那契序列的一种非常标准的方法。但是,这不够快,需要更少的工作几秒钟,而不是几分钟。而且,这个答案并没有回答我关于精度的问题。@RossGustafson我认为你应该回顾一下这种方法的性能,它不应该花费几分钟。这不是简单的“添加最后两个值”方法。这种方法只有32次迭代。我尝试过斐波那契(96)结果:结果:516807085548583323072,经过时间:00:00:00.0020192。您期望的精度值是多少?这会打断负斐波那契数。我一开始误读了您的解决方案。我看到了它在做什么。有趣的解决方案。这让我基本上达到了目的。这解决了正斐波那契数的问题,但负斐波那契数在之后仍然关闭大约10位。我想知道这是否与我的Pow方法如何处理负数以及它如何处理大数的求逆有关。@RossGustafson可以在
fib
本身中处理,以避免一开始就采用负幂,尽管我不确定目前我需要处理负幂的问题是什么计算fibonacci数,处理完美整数精度,n值高达200000。我认为我的算法将无法工作,因为浮点精度。@RossGustafson fibonacci(200000)有