1

I am trying to implement a dynamic programming problem for getting the nth number in the fibbonacci series. I am getting the output till 46th element but after that i am getting negative numbers as output..

int fib(int n, Dictionary<int, int> memo)
{
    Console.WriteLine(n +" "+ memo + "Hello");
    if (memo.ContainsKey(n))
    {
        return memo[n];
    }
    if (n<=2) return 1;
    else
    {
        memo[n] =  fib(n - 1, memo) + fib(n - 2, memo);
        return memo[n];
    }
}
Console.WriteLine("Fib " + fib(7, new Dictionary<int, int>()));
Console.WriteLine("Fib " + fib(46, new Dictionary<int, int>()));
Console.WriteLine("Fib " + fib(50, new Dictionary<int, int>()));

**Output **: Fib 13 Fib 1836311903 Fib -298632863

Expected output : fib 12586269025

3 Answers3

2

The problem is that the maximum value of an int (Int32) is 2147483647.
You already know that the value you are expecting is 12586269025 which exceeds this value.

The simple solution is to change the value data type to long (Int64) or Int128 if you want to go to 93 12200160415121876738

Int128 fib(int n, Dictionary<int, Int128> memo)
{
    Console.WriteLine("{0} [{1}] {2}", n, memo.Count, memo.Count > 0 ? memo.Last().ToString() : "??");
    if (memo.ContainsKey(n))
    {
        return memo[n];
    }
    if (n <= 2) return 1;
    else
    {
        memo[n] = fib(n - 1, memo) + fib(n - 2, memo);
        return memo[n];
    }
}
Console.WriteLine("Fib " + fib(7, new Dictionary<int, Int128>()));
Console.WriteLine("Fib " + fib(46, new Dictionary<int, Int128>()));
Console.WriteLine("Fib " + fib(50, new Dictionary<int, Int128>()));
Console.WriteLine("Fib " + fib(92, new Dictionary<int, Int128>()));
Console.WriteLine("Fib " + fib(93, new Dictionary<int, Int128>()));

Why does this matter, or more importantly, why doesn't this fail when the result of fib(n - 1, memo) + fib(n - 2, memo) is greater than the maximum value the data type can hold?

The answer is that by default the C# compiler doesn't do that. There is a healthy discussion here: No overflow exception for int in C#? but it is something that we need to be mindful of as c# developers if we are dealing with integers of large magnitudes (positive and/or negative).

If you wrap the addition expression in checked() then we can force this to fail with an exception at runtime, rather than leaving us with a seemingly valid value:

memo[n] = checked(fib(n - 1, memo) + fib(n - 2, memo));

c# with arithmetic overflow checking

Chris Schaller
  • 13,704
  • 3
  • 43
  • 81
0

The maximum size of an integer is 2147483647 (see MSDN). As your expected number, 12586269025, is larger than the max size of an int value, the value stored in the int will loop into negative values.

To resolve this, you can use a long instead of an int to store the value as it has a much larger max size at 9223372036854775807. If you really need the space, you can even use a ulong - unsigned long that wont support negative numbers but has a max size of 18446744073709551615.

Need to go higher than that? I think you will have to refactor your code at that point to generate the number.

Aria Bounds
  • 141
  • 1
  • 10
0

Maximum (signed) int value is 2147483647. When you go over this, it can reverse back and starts from -2147483647.

You can use long or even ulong types to be able to go further but you will face the same issue when the expected output will be over 9,223,372,036,854,775,807 (for long) or 18,446,744,073,709,551,615 (for ulong)

You can also go a bit further by using the double type (±1.7 × 10^308)

Kilarn123
  • 723
  • 5
  • 6