【问题标题】:Javascript recursive function not returning value?Javascript递归函数不返回值?
【发布时间】:2017-09-24 16:18:21
【问题描述】:

我正在解决一个代码战问题,我很确定我已经成功了:

function digital_root(n) {
    // ...
    n = n.toString();
    if (n.length === 1) {
        return parseInt(n);
    } else {
        let count = 0;
        for (let i = 0; i < n.length; i++) {
            //console.log(parseInt(n[i]))
            count += parseInt(n[i]);
        }
        //console.log(count);
        digital_root(count);
    }
}

console.log(digital_root(942));

基本上它应该找到一个“数字根”:

数字根是数字中所有数字的递归和。 给定n,取n的位数之和。如果该值有两个 位数,以这种方式继续减少,直到一个位数的数字 产生。这仅适用于自然数。

所以我实际上在最后得到了正确的答案,但无论出于何种原因,if 语句(我正在观察调试器运行并且它确实输入了该语句,它会说返回值是正确的值。

但随后它跳出if 语句并尝试从digital_root 主函数返回?

这是为什么?当它遇到if 语句时,它不应该摆脱这种情况吗?我很困惑为什么它试图跳出if 语句然后尝试从digital_root 不返回任何内容,所以返回值最终是未定义的?

【问题讨论】:

    标签: javascript recursion


    【解决方案1】:

    代码审查

    我的备注是下面的代码cmets

    // javascript generally uses camelCase for function names
    // so this should be digitalRoot, not digital_root
    function digital_root(n) {
        // variable reassignment is generally frowned upon
        // it's somewhat silly to convert a number to a string if you're just going to parse it again
        n = n.toString();
        if (n.length === 1) {
            // you should always specify a radix when using parseInt
            return parseInt(n);
        } else {
            let count = 0;
            for (let i = 0; i < n.length; i++) {
                //console.log(parseInt(n[i]))
                count += parseInt(n[i]);
            }
            // why are you looping above but then using recursion here?
            // missing return keyword below
            digital_root(count);
        }
    }
    
    console.log(digital_root(942));
    

    简单的递归解决方案

    考虑到其中一些事情,让我们简化digitalRoot...

    const digitalRoot = n =>
      n < 10 ? n : digitalRoot(n % 10 + digitalRoot((n - n % 10) / 10))
      
    console.log(digitalRoot(123))         //          => 6
    console.log(digitalRoot(1234))        //       10 => 1
    console.log(digitalRoot(12345))       //       15 => 6
    console.log(digitalRoot(123456))      //       21 => 3
    console.log(digitalRoot(99999999999)) // 99 => 18 => 9

    使用减少

    数字根是数字中所有数字的递归和。给定n,取n的位数之和。如果该值有两位数,则继续以这种方式减少,直到产生一位数。这仅适用于自然数。

    如果您打算使用实际的归约函数,我将在此处向您展示如何做到这一点。首先,我们将创建一个toDigits 函数,它接受一个整数,并返回一个包含其数字的数组。然后,我们将通过使用用空总和 0 初始化的 add 减速器减少这些数字来实现 digitalRoot

    // toDigits :: Int -> [Int]
    const toDigits = n =>
      n === 0 ? [] :  [...toDigits((n - n % 10) / 10), n % 10]
    
    // add :: (Number, Number) -> Number
    const add = (x,y) => x + y
    
    // digitalRoot :: Int -> Int
    const digitalRoot = n =>
      n < 10 ? n : digitalRoot(toDigits(n).reduce(add, 0))
          
    console.log(digitalRoot(123))         //          => 6
    console.log(digitalRoot(1234))        //       10 => 1
    console.log(digitalRoot(12345))       //       15 => 6
    console.log(digitalRoot(123456))      //       21 => 3
    console.log(digitalRoot(99999999999)) // 99 => 18 => 9

    【讨论】:

      【解决方案2】:

      else 内没有返回任何内容。应该是:

      return digital_root(count);
      ^^^^^^^
      

      为什么?

      digital_root 应该返回一些东西。如果我们用一位数字调用它,则执行 if 部分,并且由于我们从该 if 返回,所以一切正常。但是,如果我们提供一个由多于一位数字组成的数字,那么 else 部分就会被执行。现在,在else 部分,我们计算countdigital_root,但我们不使用那个值(应该返回的值)。上面这行代码可以拆分成两行代码,便于理解:

      var result = digital_root(count); // get the digital root of count (may or may not call digital_root while calculating it, it's not owr concern)
      return result;                    // return the result of that so it can be used from the caller of digital_root
      

      【讨论】:

      • 废话,我不太习惯使用递归。我想....你能解释一下我们为什么要退货吗?是不是因为我猜你将“未来”的价值归还给“现在”?
      • @msmith1114 检查解释!我希望它有用。
      【解决方案3】:

      它是一个递归函数,代码应该有点像这样

      function digital_root(n) {
          // ...
          n=n.toString();
          if(n.length === 1){
               return parseInt(n);
          }
          else
          {
          let count = 0;
          for(let i = 0; i<n.length;i++)
          {
          //console.log(parseInt(n[i]))
          count+=parseInt(n[i]);
          }
         //console.log(count);
         return digital_root(count);
         }
      }
      

      你应该返回相同的函数,而不是仅仅调用它来获得正确的调用堆栈

      【讨论】:

      • 为什么要使用循环和递归?在这种情况下,它几乎是一个或另一个 - 无论如何这都是无关紧要的;你的函数为digital_root(123123123)返回9,但应该返回18
      • 那么问题是为什么它返回未定义而不是值,我只是更正了代码的递归部分
      • 对于您的下一个问题,请参阅此链接了解什么是数字根thonky.com/nine-hours-nine-persons-nine-doors/digital-rootdigital_root(123123123) = 9 而不是 18,如果我的数字根概念正确。如果我错了,我很抱歉,请分享您对数字根源的看法
      • 你是对的。我把数字根误认为是数字的简单总和。谢谢
      猜你喜欢
      • 2021-03-02
      • 1970-01-01
      • 1970-01-01
      • 2012-05-29
      • 2016-05-27
      • 2015-09-19
      • 2013-03-18
      • 2015-02-25
      相关资源
      最近更新 更多