为什么我有记忆超限? C#

问题描述 投票:1回答:3

任务是:

  1. 所述Tribonacci序列是其中每个下一个元件是通过从该序列中前三个元素的和由序列。
  2. 编写发现Tribonacci序列的第N个元素的计算机程序,如果你给出序列的前三个元素和数量N.
  3. 我已经包括了计划内的约束。这个问题在系统中提交,并有一个时间限制。我打了内存限制超过去年2例。

请帮忙。

        BigInteger a = BigInteger.Parse(Console.ReadLine());
        BigInteger b = BigInteger.Parse(Console.ReadLine());
        BigInteger c = BigInteger.Parse(Console.ReadLine());

        var fibonacciNumbers = new List<BigInteger> { a, b, c };
        BigInteger N = BigInteger.Parse(Console.ReadLine());    
        if ((a < -2000000000) || (b < -2000000000) || (c < -2000000000) || (a > 2000000000) || (b > 2000000000) || (c > 2000000000) || (N > 15000) || (N < 1))
        {
            throw new Exception("Argument out of range");
        }

        while (fibonacciNumbers.Count <= N)
        {
            var previous = fibonacciNumbers[fibonacciNumbers.Count - 1];
            var previous2 = fibonacciNumbers[fibonacciNumbers.Count - 2];
            var previous3 = fibonacciNumbers[fibonacciNumbers.Count - 3];
            fibonacciNumbers.Add(previous + previous2 + previous3);
        }

        Console.WriteLine((fibonacciNumbers[(int)N - 1]));
c# memory limit fibonacci
3个回答
1
投票

因为你只需要存储最后3个数字来计算下一个你不能存储所有以前的序列值。

BigInteger prevPrev = BigInteger.Parse(Console.ReadLine());
BigInteger prev = BigInteger.Parse(Console.ReadLine());
BigInteger current = BigInteger.Parse(Console.ReadLine());

BigInteger N = BigInteger.Parse(Console.ReadLine());

for(int i = 3; i < N; i++)
{
    // calculate next number
    var next = prevPrev + prev + current;

    // shift all numbers
    prevPrev = prev;
    prev = current;
    current = next;
}

return current;

2
投票

如果我们假设你需要存储在列表前面的斐波那契结果(如果有任何的目的)?

在默认配置的CLR对象的最大大小为2GB,即使在64位。

你是存储在List占用内存斐波纳契结果。你得到OutOfMemoryException当你打2GB

你需要超过2GB的限制。为此,您需要添加gcAllowVeryLargeObjectsapp.config

<runtime>
  <gcAllowVeryLargeObjects enabled="true" />
</runtime>

在另一方面,如果你不需要斐波那契序列的所有以前的值,然后

    BigInteger f2 = BigInteger.Parse(Console.ReadLine());
    BigInteger f1 = BigInteger.Parse(Console.ReadLine());
    BigInteger f = BigInteger.Parse(Console.ReadLine());

    BigInteger N = BigInteger.Parse(Console.ReadLine());    
    if ((a < -2000000000) || (b < -2000000000) || (c < -2000000000) || (a > 2000000000) || (b > 2000000000) || (c > 2000000000) || (N > 15000) || (N < 1))
    {
        throw new Exception("Argument out of range");
    }

    while (fibonacciNumbers.Count <= N)
    {
        var fn = f2 + f1 + f;

        f2 = f1;
        f1 = f;
        f = fn;
    }

    Console.WriteLine(fn);

1
投票

有你的代码中的一些事情需要注意:

  • 为什么你前面的所有号码存储到一个数组。作为@Vadim马丁诺夫已经提到的,你只需要前三个数字(这不是斐波那契)。
  • 您可以使用BigInteger来存储计数。它可能应该安装一个32位有符号整数,因为这会已经超过2十亿迭代。随着BigInteger结构,这将已经占用太多的内存。在当前的程序结束后,你已经转换回int,所以没有使用BigInteger这里。

如果你想存储列表中的所有项目(不要问我为什么),那么请务必预先分配的列表中正确的号码(你知道它提前)和使用数组,所以你得到一个更高效的存储不需要重新分配和复制。

    var a = BigInteger.Parse(Console.ReadLine());
    var b = BigInteger.Parse(Console.ReadLine());
    var c = BigInteger.Parse(Console.ReadLine());

    var N = int.Parse(Console.ReadLine());
    if ((a < -2000000000) || (b < -2000000000) || (c < -2000000000) || (a > 2000000000) || (b > 2000000000) || (c > 2000000000) || (N > 15000) || (N < 1))
        throw new Exception("Argument out of range");

    var fibonacciNumbers = new BigInteger[N];
    fibonacciNumbers[0] = a;
    fibonacciNumbers[1] = b;
    fibonacciNumbers[2] = c;

    for (var i=3; i < N; ++i)
    {
        var previous = fibonacciNumbers[i - 1];
        var previous2 = fibonacciNumbers[i - 2];
        var previous3 = fibonacciNumbers[i - 3];
        fibonacciNumbers[i] = previous + previous2 + previous3;
    }

    Console.WriteLine(fibonacciNumbers[N - 1]);

但最好不要存储在一个阵列/列表这些项目呢。我只是想在其他问题发表意见,但请用@Vadim马丁诺夫的答案。

© www.soinside.com 2019 - 2024. All rights reserved.