所以我只是练习编码斐波那契序列的动态解决方案,它将返回第n个斐波纳契数,我不断遇到一个我无法弄清楚的问题。我得到两个正数加上负数!
代码:
int fib(int n) {
vector<int> v;
v.push_back(1);
v.push_back(1);
for (int i = 2; i <= n; i++) {
v.push_back( v.at(i-1) + v.at(i-2) );
cout << v.at(i-1) << " + " << v.at(i-2) << " = " << (v.at(i-1) + v.at(i-2)) << endl;
}
return v.at(n);
}
尝试运行fib(50),注意cout仅用于调试
答案 0 :(得分:6)
您需要将int
更改为unsigned int
或更好unsigned long long
。您的结果超出了系统int
的最大值。由于int
已签名,因此most significant bit设置后会变为负数。有关详细信息,请参阅标题为maximum value of int的Stack Overflow问题,以及binary arithmatic上的此Swarthmore College页面。如果您使用的是Visual Studio,请查看MSDN上的Data Type Ranges文章。
除了切换到unsigned long long
之外,您应该检查这样的溢出错误并抛出异常。修改后的代码版本可能如下所示。
unsigned long long fib(int n) {
vector<unsigned long long> v;
v.push_back(1);
v.push_back(1);
for (int i = 2; i <= n; i++) {
if( v.at(i-1) > (std::numeric_limits<unsigned long long>::max() - v.at(i-2)) )
throw std::overflow_error("number too large to calculate");
v.push_back( v.at(i-1) + v.at(i-2) );
cout << v.at(i-1) << " + " << v.at(i-2) << " = " << (v.at(i-1) + v.at(i-2)) << endl;
}
return v.at(n);
}
您还需要确保调用您的函数的代码可以使用try... catch...
来处理异常。这是一个例子
try {
std::cout << "2000th number = " << fib(2000) << std::endl;
} catch( std::overflow_error& ex ) {
std::cerr << ex.what() << std::endl;
}
答案 1 :(得分:2)
由于C如何将int
(signed int)存储在内存中,因此最重要的位表示负数。如果你用大数字溢出它,你就会得到负数。
参考: