Javascript递归减法

时间:2015-10-07 17:55:21

标签: javascript

示例1

function x(num) {
  if (num == 0) {
   return 1;
  }
  else {
   return (num * x(num - 1));
 }
}

x(8);
  

8 * 7 * 6 * 5 * 4 * 3 * 2 * 1

按预期结果为40320

示例2

function x(num) {
  if (num == 0) {
   return 0;
  }
  else {
   return (num + x(num - 1));
 }
}

x(8);
  

8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0

结果是36 符合预期

示例3

function x(num) {
  if (num == 0) {
   return 0;
  }
  else {
   return (num - x(num - 1));
 }
}

x(8);
  

8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0

结果 4

有人可以解释原因吗?

答案不应该是-20?

7 个答案:

答案 0 :(得分:18)

您的功能计算基本上是从右到左:

  8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0
= 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1
= 8 - 7 - 6 - 5 - 4 - 3 - 1
= 8 - 7 - 6 - 5 - 4 - 2
= 8 - 7 - 6 - 5 - 2
= 8 - 7 - 6 - 3
= 8 - 7 - 3
= 8 - 4
= 4

那是因为每次递归调用函数x时,都会尝试评估最右边的表达式。

实际上,“堆栈”看起来像这样:

  8 - x(8 - 1)
= 8 - (7 - x(7 - 1))
= 8 - (7 - (6 - x(6 - 1)))
= 8 - (7 - (6 - (5 - x(5 - 1))))
= 8 - (7 - (6 - (5 - (4 - x(4 - 1)))))
= 8 - (7 - (6 - (5 - (4 - (3 - x(3 - 1))))))
= 8 - (7 - (6 - (5 - (4 - (3 - (2 - x(2 - 1)))))))
= 8 - (7 - (6 - (5 - (4 - (3 - (2 - (1 - x(1 - 1))))))))
= 8 - (7 - (6 - (5 - (4 - (3 - (2 - (1 - 0)))))))
= 8 - (7 - (6 - (5 - (4 - (3 - (2 - 1))))))
= 8 - (7 - (6 - (5 - (4 - (3 - 1)))))
= 8 - (7 - (6 - (5 - (4 - 2))))
= 8 - (7 - (6 - (5 - 2)))
= 8 - (7 - (6 - 3))
= 8 - (7 - 3)
= 8 - 4
= 4

JavaScript对“纯”减法的评估是:

8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0; // -20

答案 1 :(得分:17)

因为你的功能是从右到左有效地计算:

8 - (7 - (6 - (5 - (4 - (3 - (2 - (1 - 0))))))) => 4

而不是:

8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0 => -20

答案 2 :(得分:2)

递归的第一个减法从最后两个数字开始并向后运行:

x = 8-7-6-5-4-3-2-(1-0)
x = 8-7-6-5-4-3-(2-1)
x = 8-7-6-5-4-(3-1)
x = 8-7-6-5-(4-2)
x = 8-7-6-(5-2)
x = 8-7-(6-3)
x = 8-(7-3)
x = (8-4)
x = 4

答案 3 :(得分:2)

用递归写的等式8-7-6-5-4-3-2-1-0需要有重复的东西。 8不是它的一部分,因为它不会减去它。所以你应该这样做:

import scrapy
import time
from odds.items import OddsItem
from selenium import webdriver


class OddsSpider(scrapy.Spider):
    name = "odds"
  ...... other code ....

代码就像

Traceback (most recent call last):
  File "/usr/local/bin/scrapy", line 11, in <module>
    sys.exit(execute())
  File "/usr/local/lib/python2.7/dist-packages/scrapy/cmdline.py", line 142, in execute
    cmd.crawler_process = CrawlerProcess(settings)
  File "/usr/local/lib/python2.7/dist-packages/scrapy/crawler.py", line 209, in __init__
    super(CrawlerProcess, self).__init__(settings)
  File "/usr/local/lib/python2.7/dist-packages/scrapy/crawler.py", line 115, in __init__
    self.spider_loader = _get_spider_loader(settings)
  File "/usr/local/lib/python2.7/dist-packages/scrapy/crawler.py", line 296, in _get_spider_loader
    return loader_cls.from_settings(settings.frozencopy())
  File "/usr/local/lib/python2.7/dist-packages/scrapy/spiderloader.py", line 30, in from_settings
    return cls(settings)
  File "/usr/local/lib/python2.7/dist-packages/scrapy/spiderloader.py", line 21, in __init__
    for module in walk_modules(name):
  File "/usr/local/lib/python2.7/dist-packages/scrapy/utils/misc.py", line 71, in walk_modules
    submod = import_module(fullpath)
  File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/home/yohack/scraping_scrapy/odds/odds/odds/spiders/odds.py", line 3, in <module>
    from odds.items import OddsItem
ImportError: No module named items

答案 4 :(得分:1)

正如其他人所回答的那样,减法正在从右到左进行:

x = 8-7-6-5-4-3-2-(1-0)
x = 8-7-6-5-4-3-(2-1)
x = 8-7-6-5-4-(3-1)
x = 8-7-6-5-(4-2)
x = 8-7-6-(5-2)
x = 8-7-(6-3)
x = 8-(7-3)
x = (8-4)
x = 4

您正在寻找的是加法的反转,可以写成如下:

function addition(num) {
    if (num == 0) {
        return 0;
    }
    else {
        return (num + addition(num - 1));
    }
}

function subtraction(num) {
    return num - addition(num - 1);
}

调用减法(8)将产生-20,因为它减去所有较小数字的总和,而原始函数减去所有较小的数字。

答案 5 :(得分:1)

详细说明我的评论......

减法(与乘法和加法不同,这解释了为什么你的其他例子有效)不是可交换的,而JavaScript的评价是从左到右,而你的函数有效地从右到左。

要使用现有代码获得正确的结果,您可以使用减法是负数的加法这一事实。在链中,只有最左边的数字是正数。重新使用总和功能:

function sub(num) {
    return num - sum(num - 1)
}

一个纯递归的单函数解决方案需要一个额外的参数来知道从哪里停止(从零开始),或者为第一个调用创建一个特殊情况(添加而不是减去第一次调用除外)。

当然,如果你不介意算术作弊,你可以线性化为

function sub(num){ return num - (num*(num-1)/2) }

答案 6 :(得分:0)

为什么-20和减法不是从8开始? 因为函数在到达0函数开始减法后循环通过所有这些数字。但在所有功能进行x(num - 1)操作之前。 你可以简单地从8 * 7 * 6 * 5 * 4 * 3 * 2 * 1计算出该函数首先乘以2 * 1 = 2然后2 * 3 = 6然后再6 * 4 ......