我只是编写了递归Fibonacci算法的改进线性版本,并意识到我的布尔表达式看起来非常糟糕且难以理解。是否有清洁方式来做我想做的事情?
int fibonacci(int num) {
if (num <= 1)
return num;
// starts looking ugly here
int a = intExists(num-1);
int b = intExists(num-2);
bool aAndB = (a != -1 && b != -1);
bool justA = (a != -1 && b == -1);
bool justB = (a == -1 && b != -1);
int number = 0;
if (aAndB)
number = (a + b);
else if (justA)
number = (a + fibonacci(num - 2));
else if (justB)
number = (fibonacci(num-1) + b);
else
number = (fibonacci(num - 1) + fibonacci(num - 2));
map.push_back(Pair(num, number));
return number;
}
由于
答案 0 :(得分:2)
为什么不将a
和b
设为bool
,如果true
和a == -1
则另有false
。然后,表达式将变得更容易处理。
答案 1 :(得分:2)
如果你在谈论:
bool aAndB = (a != -1 && b != -1);
然后我会说,“不。”
此代码看起来非常适合我。 aAndB
在它出现的那一刻被初始化,条件非常明确。当你第一次开始使用C ++时,这可能看起来有点奇怪,但在你知道它之前它将是第二天性而其他结构看起来很愚蠢。
如果您不打算更改aAndB
const
,我建议做一件事:
const bool aAndB = (a != -1 && b != -1);
这更具表现力。
它还可以为编译器提供额外的优化代码的机会。
记住 - 为 human 编写代码以便理解。不适合电脑理解。
答案 2 :(得分:1)
可以执行switch语句来清理if else语句。除此之外只需添加评论
答案 3 :(得分:1)
您可以将其重写为使用条件分支,如下所示:
int fibonacci(int num) {
if (num <= 1)
return num;
int a = intExists(num-1);
int b = intExists(num-2);
const bool isA = (a != -1); // change in the definition
const bool isB = (b != -1); // change in the definition
int number = 0;
if (isA && isB)
number = (a + b);
else if (isA) // conditionnal branching
number = (a + fibonacci(num - 2));
else if (isB) // conditionnal branching
number = (fibonacci(num-1) + b);
else
number = (fibonacci(num - 1) + fibonacci(num - 2));
map.push_back(Pair(num, number));
return number;
}
答案 4 :(得分:1)
我假设intExists(n)
查找map
,如果在其中找到n
,则返回fibonacci(n)
,否则返回-1
。然后你可以这样做:
int fibonacci(int num) {
if (num <= 1)
return num;
int a = intExists(num-1);
int b = intExists(num-2);
if (a == -1) // if a wasn't found, then compute it
a = fibonacci(num-1);
if (b == -1) // if b wasn't found, then compute it
b = fibonacci(num-2);
int number = a + b;
map.push_back(std::make_pair(num, number));
return number;
}
<强>加成:强>
以下是基于Binet's formula的另一个完全不同的fibonnacci()
实现:
#include <cmath>
int fibonacci(int n) {
static const double e1 = 1.6180339887498948482045868343656; // = (1 + sqrt(5)) / 2
static const double e2 = -0.61803398874989484820458683436564; // = (1 - sqrt(5)) / 2
static const double c = 0.44721359549995793928183473374626; // = 1 / sqrt(5);
double f = c * (std::pow(e1, n) - std::pow(e2, n));
return static_cast<int>(f + 0.5);
}
int main() {
for (int n = 1; n < 15; ++n)
std::cout << fibonacci(n) << ' ';
}
输出:
1 1 2 3 5 8 13 21 34 55 89 144 233 377
答案 5 :(得分:0)
普通C ++代码足够干净:
bool a = intExists(num-1);
bool b = intExists(num-2);
if (a && b) {
//
} else if (a) {
//
} else if (b) {
//
} else {
//
}
答案 6 :(得分:0)
int a = intExists(num-1);
int b = intExists(num-2);
bool aAndB = (a != -1 && b != -1);
bool justA = (a != -1 && b == -1);
bool justB = (a == -1 && b != -1);
快速了解您采取的方法。 在什么情况下justB
可以true
?(提示:从不)
这应该可以帮助您简化您的方法,尽管有比 memoization 更好的方法。
答案 7 :(得分:0)
更改intExists
以返回布尔值,您可以执行类似的switch-case语句:
bool a = intExists(num-1);
bool b = intExists(num-2);
switch ((a << 1) + b) {
default: // none exists
case 1: // only b exist
case 2: // only a exist
case 3: // both exists
}
理由是用二进制数转换那些布尔值
答案 8 :(得分:0)
略微激烈的重写是让外部函数处理查找表 这样,您不需要一次关注多个值。
这个使用map
所以我没有必要写这么多来测试它,但它应该很容易适应:
std::map<int, int> table;
int fibonacci(int num);
int value(int num)
{
int result = table[num];
if (!result)
{
result = fibonacci(num);
table[num] = result;
}
return result;
}
int fibonacci(int num)
{
if (num <= 2)
return 1;
return value(num - 1) + value(num - 2);
}