【问题标题】:Eloquent JavaScript 2nd Edition recursion exercise solutionEloquent JavaScript 第 2 版递归练习解决方案
【发布时间】:2021-06-12 15:09:45
【问题描述】:

我试图解决在线书籍eloquentjavascript 2nd edition的递归练习:

问题是这样的:

我们已经看到 %(余数运算符)可以用来测试是否 一个数是偶数还是奇数,使用 % 2 检查它是否可以被整除 二。这是另一种定义(正数,整数)数的方法 是偶数还是奇数:

  • 零是偶数。
  • 一个是奇数。
  • 对于任何其他数 N,其均匀度与 N - 2 相同。

定义一个递归函数isEven对应这个描述。 该函数应该接受一个数字参数并返回一个布尔值。

在 50 和 75 上测试它。看看它在 -1 上的表现。为什么?你能想 有办法解决这个问题吗?

这是我尝试过的并且有效:

function isEven(number) {
    if (number == 0) {
        return true;
    } else {
        return (-number % 2 == 0) ? true : false;
    }
    return isEven(number - 2);
}

console.log(isEven(-1));

但是,这似乎是一个错误的答案,因为据我了解,作者希望我使用 - 2 方法。我想知道这是否确实是正确的答案,或者如果它是错误的,有人可以指出我正确的方向。

【问题讨论】:

    标签: javascript recursion


    【解决方案1】:

    我认为您感到困惑的原因是您不了解递归的工作原理。它是 n-2 的原因是,它取数字并减去 2 直到它是零或一。因此给我们一个真假。

    希望对您有所帮助。阅读递归过程的工作原理。

    【讨论】:

      【解决方案2】:

      下面提供了不使用模运算符 % 或 JavaScript 中的任何其他内置函数的替代解决方案。这个解决方案依赖于使用另一个递归来改变数字的负值。

      function isEven(number) {
          if (number < 0) {
              return isEven(-number);
          } else if (number == 1) {
              return false;
          } else if  (number == 0) {
              return true;
          } else {
              return isEven(number - 2);
          }
      }
      
      console.log(isEven(50)); // true
      console.log(isEven(75)); // false
      console.log(isEven(-1)); // false
      

      【讨论】:

      • 我一遍又一遍地阅读本书中的递归,查看您的代码,但它对我来说仍然是零意义。为什么我们调用 isEven(number - 2)?这是在做什么?
      • "对于任何其他数 N,其均匀度与 N - 2 相同。"
      • 使用三元运算符 - 函数 isEven (x) { return x > 1 ? isEven(x-2) : x===1 ?错误:x===0?真:是偶数(-x); }
      【解决方案3】:

      我们调用 isEven(number -2) 以返回函数的顶部,其中最初输入的数字比以前少 2,它会一直这样做,直到数字为 1 或 0,然后它将是能够返回布尔值 true 或 false(偶数或奇数)。

      【讨论】:

        【解决方案4】:

        我认为问题在于创建 isEven 函数而不使用 mod/%/remainder 操作

        function isEven(number) {
          if (number < 0) {
            number = Math.abs(number);
          }
          if (number===0) {
            return true;
          }
          if (number===1) {
            return false;
          }
          else {
            number = number - 2;
            return isEven(number);
          }
        
        }
        

        我想添加到这个很重要

        1. 它不处理字符串
        2. 它不处理浮点数
        3. 不要将其放入生产应用程序中

        【讨论】:

        • 我也是这么认为的,我的回答感觉我没有完成任务:(
        • console.log(isEven(-3));导致递归错误太多。
        • 这不是生产代码,而是关于练习内容的想法。我认为没有必要投反对票,但我知道什么......
        • 可以使用Math.abs处理负数
        • @levi - 刚刚更新它
        【解决方案5】:
        function isEven(n) {
         n = Math.abs(n);
          if (n==0) 
            return true;
          else if (n==1)
            return false;
          else 
            return isEven(n-2);
        }
        
        console.log(isEven(-50)); // → true
        console.log(isEven(75)); // → false
        console.log(isEven(-75)); // → false
        console.log(isEven(-1)); // → false
        

        【讨论】:

        • 欢迎来到 StackOverflow!请添加一些关于为什么此代码有效的解释。
        【解决方案6】:
        var isEven = function(n) {
          // Get the absolute value of the number
          // so we don't have to bother with negatives
          n = Math.abs(n);
        
          // We know that if we subtract 2 from our number
          // until it is equal to zero, our number was even
          // If our number isn't zero, this statement will be skipped
          if(n === 0) return true;
        
          // We know that if we subtract 2 from our number
          // and it reaches a value of 1, it isn't even
          // If our number isn't 1, this statement will be skipped
          if(n === 1) return false;
        
          // We subtract 2 from our original number and pass it
          // back in to this function to check it over and over again
          // until one of the conditions is met and the function can
          // return a result
          return isEven(n - 2);
        }
        
        // We test our function here
        console.log(isEven(-21));
        

        这是我能想到的最精简的方法。请注意,我们从自身内部调用 isEven 函数并传入 n - 2 的值。这将不断地从我们的数字中减去 2 并检查它是否等于 0 或 1,直到我们得到正确的结果并返回相应的布尔值.

        我希望这能把事情弄清楚一点。

        【讨论】:

          【解决方案7】:

          下面的代码怎么样?似乎对我有用。

          /*if > 1 keep looking, otherwise return reverse boolean value. 
          If negative value, inverse, to answer the last part of the question... 
          Also needed to use parseInt as the text value I used, 
          was considered a string value!
          This being a recursive function which really isn't necessary, 
          means that in javascript we will get a 
          stack size exceeded error when the number becomes too large.*/
          
          function isEven(x) {
              return (x>1)?isEven(x-2):(x>=0)?!x:isEven(-x);
          }
          

          【讨论】:

          • 对于那些对递归等基本概念有困难的人来说,给出代码高尔夫解决方案可能没有帮助。
          【解决方案8】:

          本书希望这些值的以下 console.log 输出

          console.log(isEven(50));
          // → true
          console.log(isEven(75));
          // → false
          console.log(isEven(-2));
          // → ??
          

          提示说“当给定一个负数时,函数将一次又一次地递归,给自己传递一个越来越多的负数,因此离返回结果越来越远。它最终会用完堆栈空间并中止。”所以我不确定我得到的是否代表了这一点,但我的代码和 console.log 输出如下所示:

             let isEven = function(num) {
                   if (num ===0) {
                       return true
                   } else if (num===1){
                       return false
                   } else {
                       return isEven(num-2)
                   }
              }    
          
          console.log(isEven(50));
          // → true
          console.log(isEven(75));
          // → false
          console.log(isEven(-2));
          // → RangeError: Maximum call stack size exceeded (line 3 in function isEven)```
          

          【讨论】:

            【解决方案9】:

            该问题要求您不要不使用模数运算符 (%)。

            // Your code here.
            var isEven = function(a){
              if (a == 0){ //case 1 : zero is even
                return true;
              }
              else if(a == 1){ //case 2: one is odd 
                return false;
              }
                else {
                  return isEven(Math.abs(a-2)); //solves case 3 (negative numbers)
                }
            }
            
            console.log(isEven(50));
            // → true
            console.log(isEven(75));
            // → false
            console.log(isEven(-1));
            // → ?? ....false
            

            【讨论】:

              【解决方案10】:

              这是来自网站的"correct" 答案。我用引号说“正确”是因为我不明白第二个“else if”语句的return isEven(-n)。为什么作者加入了将n变成正数的选项?

              function isEven(n) {
                if (n == 0)
                  return true;
                else if (n == 1)
                  return false;
                else if (n < 0)
                  return isEven(-n);
                else
                  return isEven(n - 2);
              }
              

              无论如何,我想我会分享,因为我没有看到任何人发布此答案。

              【讨论】:

              • 而不是依赖外部方法Math.abs(number) 就像其他人在他们的答案中在这里发布的那样,这样做是作者选择保持解决方案完全独立的方式。整个函数可以读作"如果数为零,则为偶数;如果数为1,则为奇数;如果数为负,则其偶数是其正值的偶数;否则其均匀度与数字减二相同” — 这与练习中陈述问题的方式几乎完全相同。
              • 这个答案在功能上等同于this one by user2578173(忽略由于 if 子句重新排序导致的微小速度差异)。
              【解决方案11】:
              //define recursive function isEven takes a positive whole number
              //returns true if even
              function isEven(x) {
                //define innner function to loop over value
                function find(current) {
                  //check if value == 0, return true
                  if (current == 0) { 
                    return true
                  //check if value == 1 return false
                   } else if (current == 1)  {
                      return false
                  //loop over value, subtracting 2 each time until either 0 or 1
                  //which returns the approriate true/false value based on evenness
                   } else {
                   console.log(current)
                   return find(current -2)
                  }
                }
                  return find(x)
              }
              

              【讨论】:

                【解决方案12】:

                如果数字是1-1所以ODD,函数返回false
                如果数字是 0 所以 EVEN,它返回 true

                如果 then 数字也不是 1,-1也不是 0 我们必须先检查数字是正数还是负数,

                如果数字为小于-1,我们再次调用函数将数字增加2直到我们得到 -1 或 0;
                如果数字是并且大于1,我们再次调用函数但是将数字减少2直到我们得到 1 或 0;

                例如,数字是 5 ->
                它是正数并且大于 1,所以一遍又一遍地调用函数并将数字减 2,直到结果为0 或 1:
                5->3->1 //->假

                    function isEven(num) {
                    if (num == 1 || num == -1) {
                        return false;
                    } else if (num == 0) {
                        return true;
                    } else {
                        if (num < -1) {
                            return isEven(num + 2);
                        } else {
                            return isEven(num - 2);
                        }
                    }
                }
                

                测试结果:

                console.log(`-35 is even: ${isEven(-35)}`); //-> false
                console.log(`-1 is even: ${isEven(-1)}`);  //-> false
                console.log(`0 is even: ${isEven(0)}`);  //-> true
                console.log(`32 is even: ${isEven(32)}`);  //-> true
                

                【讨论】:

                • 使用if (num &lt; 0) {return isEven(- num)}处理负数可能更容易
                【解决方案13】:

                我在上面看到了很多使用数学函数和模运算符的示例。但我猜作者期望一个简单的递归函数来让读者理解它的功能以及如果没有正确定义它会如何导致重复的函数调用并最终导致堆栈溢出。相信下面这段代码可以帮助你理解:

                function isEven(n){
                  if(n==0){
                    return true;
                  } else if(n==1){
                    return false;
                  } else {
                    return isEven(n-2);
                  }
                }
                console.log(isEven(50));
                console.log(isEven(75));
                console.log(isEven(-1));

                【讨论】:

                  【解决方案14】:
                  function isEven(num){
                   if(num %2 == 0) {
                   return true;
                  } else {
                    return false;
                   }
                  }
                  
                  console.log(isEven(50));
                  // → true
                  
                  console.log(isEven(75));
                  // → false
                  
                  console.log(isEven(-1));
                  // → ??
                  

                  【讨论】:

                  • 欢迎来到 StackOverflow,在此之前您可能需要阅读 how to post an answer。提供一些上下文来解释您发布该代码的原因以及它的作用。还可以考虑花时间格式化您的答案,以便读者容易理解。
                  • 请对你的解决方案做一些解释:)
                  • 您的解决方案完全按照问题陈述的要求执行。它正在寻找“另一种定义正整数是偶数还是奇数的方法”...... other 而不是 使用余数 % 运算符。跨度>
                  【解决方案15】:
                  function isEven(number) {
                      while(number>= -1)
                      {   
                          return isEven(number-2) == 0 && number>-1 ? true : false;
                      }
                  }
                  console.log(isEven(-1));
                  

                  【讨论】:

                  • 为什么完全没用的 while 循环?为什么是无用的三元运算符?
                  • while 循环是控制递归,三元运算符是检查偶数和奇数
                  • 如果不更改分配给number 的值,该循环如何控制递归?
                  【解决方案16】:

                  我希望这会有所帮助:

                  const evenOrOdd = (N) => {
                      if (Math.abs(N) === 0) {
                          return console.log('Even');
                      } else if (Math.abs(N) === 1) {
                          return console.log('Odd');
                      }
                      evenOrOdd(Math.abs(N) - 2);
                  };
                  

                  Google Chrome Console code results:

                  它利用问题的所有三个给定论点。它可以处理负整数。它不使用模运算符。最后,我没有看到任何与我提供的代码相似的 sn-p 代码,因此我很想分享我能分享的内容。

                  【讨论】:

                  • 我们为什么要这样做?您对您的代码有任何疑问吗?然后请打开一个新问题 - 不要在答案部分发布问题
                  • 你好 Nico,我想我把你弄糊涂了。我实际上是在建议对上面提供的初始问题的回答。
                  • 函数 'evenOrdOdd' 所做的是通过反复将 'N'(输入的数字)减去 2 来递归自身,直到它到达等于 0 或 1 的数字。最后,对应的console.log 值(“偶数”或“奇数”)将根据结束数字(0 或 1)出现。
                  • 为什么要使用全新的代码块?为什么不帮助 OP 在自己的代码中找到错误呢?
                  • 当然可以——但是你应该强调是什么让你的代码比所有其他解决方案更好。它包含哪些内容比任何其他解决方案都“改进”了?
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-10-02
                  • 2013-11-12
                  • 2018-08-22
                  • 1970-01-01
                  • 2013-07-22
                  • 2017-02-10
                  • 2015-10-25
                  相关资源
                  最近更新 更多