所以我试图让自己熟悉递归和 Javascript。所以我写了一个简单的方法来尝试一下。我对 Javascript 语法很陌生,所以我不确定我哪里出错了。这是方法。
export const IsEven = (n) => {
if(n > 1){
n -= 2;
IsEven(n);
}
else{
var bool = NumberToBool(n);
return bool;
}
}
单步执行时,n 确实达到了 0 或 1,并将其定义为 true 或 false。但是,该方法不会在 return 语句处停止。相反,它转过身开始将 2 添加到 n。我无法理解这怎么可能,有没有人知道发生了什么?
谢谢
答案 0 :(得分:2)
可以使用mathematical induction解决绝大多数递归问题-
n
为负,返回isEven(-n)
的结果n
为零或更大。如果 n
大于 1,则返回递归子问题的结果,isEven(n - 2)
n
既不为负也不大于 1。这意味着 n
是零或一。零是偶数,一是奇数。 return n == 0
为我们提供了正确的结果。const isEven = (n) => {
if (n < 0) return isEven(n * -1) // 1. n is negative
else if (n > 1) return isEven(n - 2) // 2. n is 2 or more
else return n == 0 // 3. n is 0 or 1
}
for (let i = -10; i<10; i++)
console.log(i, isEven(i))
递归是一种函数式遗产,因此将其与函数式风格结合使用会产生最佳效果。 if
语句不计算为值,而是依赖于 return
之类的副作用来计算结果。下面我们使用计算为一个值的表达式,它允许我们跳过命令式风格带来的很多语法噪音。现在 isEven
读起来更像是一个公式 -
const isEven = n =>
n < 0
? isEven(n * -1) // 1. n is negative
: n > 1
? isEven(n - 2) // 2. n is 2 or more
: n == 0 // 3. n is 0 or 1
for (let i = -5; i < 5; i++)
console.log(i, isEven(i))
n | isEven(n) |
---|---|
-5 | 假 |
-4 | 真实 |
-3 | 假 |
-2 | 真实 |
-1 | 假 |
0 | 真实 |
1 | 假 |
2 | 真实 |
3 | 假 |
4 | 真实 |
isEven
可以使用协同对应物 isOdd
来定义,其中每个都可以根据另一个来定义。这种技术称为mutual recursion -
const isEven = n =>
n < 0
? isEven(-n)
: n == 0
? true
: isOdd(n - 1)
const isOdd = n =>
n < 0
? isOdd(-n)
: n == 0
? false
: isEven(n - 1)
for (let i = -5; i < 5; i++)
console.log(`i:${i} isEven:${isEven(i)} isOdd:${isOdd(i)}`)
n | isEven(n) | isOdd(n) |
---|---|---|
-5 | 假 | 真实 |
-4 | 真实 | 假 |
-3 | 假 | 真实 |
-2 | 真实 | 假 |
-1 | 假 | 真实 |
0 | 真实 | 假 |
1 | 假 | 真实 |
2 | 真实 | 假 |
3 | 假 | 真实 |
4 | 真实 | 假 |