- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以下函数作为本练习的介绍,说明了用加法定义的乘法。这是最简单的“容易写下来”的递归定义。
(define (star a b)
(if (= b 0)
0
(+ a (star a (- b 1)))))
当我看到这一点时,我做的第一件事就是按照之前的练习,编写一个不会破坏堆栈的迭代形式:
(define (star a b)
(star-iter a b 0))
(define (star-iter a counter sum)
(if (= counter 0)
sum
(star-iter a (- counter 1) (+ a sum))))
练习 1.17 鼓励我们找到一个不变量,以减小问题规模,其想法是从 O(n) 到 O(logn) 步数(当执行该特定步骤时,无需执行任何更新结果的事情 - 我们在该步骤中所做的就是减少/转换问题定义 - 这就是“找到不变量”的含义)(参见下面第一个代码块的第 3 行 - 没有添加任何内容导致该步骤)。
对于快速版本,问题说我们应该使用函数halve
和double
,并且似乎暗示这些函数可以作为机器操作使用(恒定时间?)。我已经实现了“快速”版本,只是欺骗了这些函数,如下所示:
(define (fast-star a b)
(cond ((or (= b 0) (= a 0)) 0)
((even? a) (fast-star (/ a 2) (* 2 b)))
(else (+ a (fast-star a (- b 1))))))
迭代形式的相同内容(即 O(1) 空间):
(请注意上面第 4 行中的 + a
如何移动到下面第 6 行末尾的累加器,以将其置于尾部位置)
(define (fast-star b)
(fast-star-iter a b 0))
(define (fast-star-iter a b sum)
(cond ((or (= a 0) (= b 0)) sum)
((even? a) (fast-star-iter (/ a 2) (* 2 b) sum))
(else (fast-star-iter a (- b 1) (+ a sum)))))
所以这是一个“有什么意义”的问题 - 这些函数比上面给出的前两个函数慢。这四个函数中的第一个会破坏堆栈,因此它没有用。但第二个没有。在我的测试中,这个版本比这两个“快速”版本中的任何一个都更快。
我在这里遗漏了什么吗?很好奇是否有一种方法可以实现减半和双倍,以便它们实际上给出此处建议的 log(n) 结果。一定有,否则这个问题就没有意义。
请注意,如果 a 和 b 的大小不同,则它们的顺序很重要 - 例如乘以 2、100 次或 100、2 次,第一个是 100 步,后一个是 2 步。这将是稍后添加到此功能中的内容。但首先对 half
和 double
感到好奇。
最佳答案
您的代码中有一个微妙的错误,这就是它很慢的原因。对于版本 3 和 4,这应该可以解决这个问题:
(define (fast-star a b)
(cond ((or (= b 0) (= a 0)) 0)
((even? b) (fast-star (* 2 a) (/ b 2.0)))
(else (+ a (fast-star a (- b 1))))))
(define (fast-star-iter a b sum)
(cond ((or (= a 0) (= b 0)) sum)
((even? b) (fast-star-iter (* 2 a) (/ b 2.0) sum))
(else (fast-star-iter a (- b 1) (+ a sum)))))
这个想法是在每次迭代中不断添加a
并减少b
,但根据情况有时您会减少 b
有时你会加倍!另请注意,我将 b
除以 2.0
以消除精确算术,这样速度较慢。
当然,您也可以反过来做:添加 b
并减少 a
- 重要的是要一致它,将一个参数的问题减半,并将另一个参数加倍,加倍的参数就是我们需要添加到最终结果中的参数。
关于scheme - SICP Ex。 1.17 - "fast-multiply"比 "multiply"慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62150288/
我目前正在研究 SICP 关于逻辑编程的部分,但我被困在有关逻辑推导的示例中,尤其是附加到表单规则。它们是如何工作的?我不太明白的是第二条规则是如何取消第一个列表的。例如,给定: (规则(附加到表单(
据我了解,著名的SICP讲座视频: http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-struc
我已经以“边做边学”的方式编程了将近 2 年,我认为自己相当不错,但是,我真的希望为计算机科学/计算机工程打下良好的基础,大多数人建议我开始关闭 SICP。 (计算机程序的结构和解释) 我想知道 这是
我正在研究计算机程序的结构和解释。马上,有两个词被使用,似乎表示一些特定的概念:计算过程和程序。我有一个简单的问题。在 Abelson 和 Sussman 的用法上下文中,这些术语的定义是什么? 最佳
求值器完整实现代码我已经上传到了GitHub仓库: TinySCM ,感兴趣的童鞋可以前往查看。这里顺便强烈推荐UC Berkeley的同名课程 CS 61A 。 在这个层次结构
即使在变化中,它也丝毫未变。 ——赫拉克利特 吾犹昔人,非昔人也。 ——僧肇 前面我们介绍了组成程序的各种基本元素,看到了如何把基本过程和基本数据组合
绪论 我们在第一章引进复合过程时,采用了求值的代换模型定义了将过程应用于实参(arguments)的意义: 将一个复合过程应用于一些实参,也就意味着用实参替换过程体里对应的形参(f
绪论 我们已经介绍过数据抽象,这是一种构造系统的方法学,它能够使程序中的大部分描述与其所操作的数据对象的具体表示无关,比如一个有理数程序的设计与有理数的实现相分离。这里的关键是构筑数据抽象屏障
我在这里问了几个关于 Scheme/SICP 的问题,答案经常涉及使用 apply 过程,我在 SICP 中没有看到过,在本书的索引中,它只列出了一次,结果是脚注。 一些使用示例基本上是这个问题的每个
我目前正在通过计算机程序的结构和解释来完成本书和 Brian Harvey(他有时很搞笑)的讲座,但是我还没有真正拥有我的“啊哈!时刻”区分函数和程序。 现在,我在讲座和阅读之外进行了研究,发现了一些
关于 SICP 3.5 我自己的实现如下 (define (delay exp) (lambda () exp)) (define (force delayed-obj) (delayed-obj
考虑以下定义: (define foo (lambda (x y) (if (= x y) 0 (+ x (foo (+
我正在使用 SICP 书并且做了这个练习: 1.11 函数 f 由以下规则定义:如果 n 3. 编写一个通过递归过程计算 f 的过程。编写一个通过迭代过程计算 f 的过程。 递归过程很简单。迭代的更难
我在阅读 SICP 时遇到了一个问题,在第 1 章中有一个名为 counting change 的示例,我需要在 scheme 中编写一个程序来计算给定一半的任何给定数字的可能变化方式- 美元、25
我正在使用 SICP 这本书,我正在为递归与迭代过程的概念而苦苦挣扎。在问题 1.17 他们问这个: 练习 1.17。本节中的取幂算法基于通过重复乘法执行取幂。类似地,可以通过重复加法来进行整数乘法。
在关于不动点的第 1 章中,书上说我们可以使用以下方法找到某些函数的不动点 f(x) = f(f(x)) = f(f(f(x))) .... 那些功能是什么? 当我将它重写为 y = y/2 时它对
我正在学习 SICP 这本很棒的书。尽管很棒,但它确实是一本难懂的书。我遇到了长尾递归问题,id est,迭代过程的递归定义。 这本书介绍了阶乘的迭代过程: (define (factorial n)
我正在使用 SICP 这本书并尝试解决这个练习: 1.2.4 Exponentiation Exercise 1.18. Using the results of exercises 1.16 and
这是生成递归过程的 SICP 的阶乘过程。 (define (factorial n) (if (= n 1) 1 (* n (factorial (- n 1)))))
这个问题在这里已经有了答案: SICP recursive process vs iterative process: using a recursive procedure to generate
我是一名优秀的程序员,十分优秀!