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));
