Почему я получаю System.ArithmeticException с C# Nuget BigInteger 1.0.7? - PullRequest
1 голос
/ 23 февраля 2020

Итак, я изучил C# и протестировал несколько простых алгоритмов. Я сделал этот простой класс, который предоставляет рекурсивную функцию числа Фибоначчи. Я использую памятку (программирование Dynami c) для хранения ранее найденных номеров. Вот код:

    using Godot;
    using System.Collections.Generic;

    public class Exercise1 : Node {
      private BigInteger teste = new BigInteger(1);
      private Dictionary<BigInteger,BigInteger> memory = new Dictionary<BigInteger,BigInteger>();
      public override void _Ready() {
        RunBigIntegerCraziness();
      }

    private void RunBigIntegerCraziness() {
      for (int i = 0; i < 31227; i++) {
        GD.Print($"fib number {i} is {fib(new BigInteger(i))}");
      }
    }

    private BigInteger fib(BigInteger n) {
      if (memory.ContainsKey(n)) {
        return memory[n];
      }

      if (n <= 2) {
        memory[n] = 1;
        return 1;
      }

      memory[n - 2] = fib(n - 2);
      memory[n - 1] = fib(n - 1);

      return memory[n - 2] + memory[n - 1];
    }
    }

Игнорировать часть «Годо». Просто я тестировал это внутри игрового проекта. Все компилируется нормально, но я могу рассчитать только до Фибоначчи. 3226. Если я go для чисел, равных 3227 и более, я получаю это исключение:

[...] число 3225 фиби это число 3226 фиби, это

Исключение необработанное: система. ArithmeticException: переполнение или недостаточное значение в операции arithmeti c. в BigInteger.op_Addition (BigInteger bi1, BigInteger bi2) [0x000fa] в: 0 в Exercise1.fib (BigInteger n) [0x000a8] в /Users/rafael/gamedev/godot/mytests/CSharpStudy/study_classes/Exercise1.cs:31 Exercise1.RunBigIntegerCraziness () [0x00006] в /Users/rafael/gamedev/godot/mytests/CSharpStudy/study_classes/Exercise1.cs:15 at Exercise1._Ready () [0x00001] в / Users / rafael / gamedev / godot / my CSharpStudy / study_classes / Exercise1.cs: 10 Терминальный процесс завершен с кодом выхода: 1

Разве «BigInteger» не должен обрабатывать довольно большие числа ??

1 Ответ

4 голосов
/ 23 февраля 2020

В источнике этого BigInteger есть:

// maximum length of the BigInteger in uint (4 bytes)
// change this to suit the required level of precision.
private const int maxLength = 70;

Длина отсчитывается в конечностях , каждая часть составляет 32 бита в этой реализации. Кроме того, самый верхний бит самой верхней конечности рассматривается как знаковый бит. Следовательно, без изменения источника максимальное число, которое может быть сохранено в этом типе BigInteger (этот предел не применяется к BigInteger в System.Numerics), составляет 2 70 * 32-1 * 1009. * -1, или, другими словами, доступно 2239 «нормальных» битов.

Это допускает некоторые довольно большие целые числа, но недостаточно большие: согласно Wolfram Alpha fib (3227 ) требует чуть более 2239 бит, поэтому он не подходит.

...