在LISP中使用'ash'来执行二分搜索?

时间:2011-12-26 10:16:46

标签: lisp common-lisp land-of-lisp

所以,我现在正在阅读Land of Lisp,而且Lisp与我见过的其他编程语言完全不同。

无论如何,本书提供了一些我们打算输入CLISP REPL的代码:

(defparameter *small* 1)
(defparameter *big* 100)

(defun guess-my-number ()
    (ash (+ *small* *big*) -1))

(defun smaller ()
    (setf *big* (1- (guess-my-number)))
    (guess-my-number))

(defun bigger ()
    (setf *small* (1+ (guess-my-number)))
    (guess-my-number))

现在,基本目标是创建一个数字猜谜游戏,其中用户/玩家选择一个数字,然后计算机试图猜测该数字。它通过让玩家报告计算机猜测的数字是高于还是低于玩家的号码来执行“二分搜索”,以找到玩家的号码。

我对ash功能有点困惑。我的理解是这对二进制搜索至关重要,但我不确定为什么。这本书在某种程度上解释了它的作用,但它有点令人困惑。

ash功能有什么作用?为什么通过*small*添加到*big*-1的参数?它是如何工作的?它对二进制搜索有什么作用?

3 个答案:

答案 0 :(得分:4)

Google为您提供this page,其中解释了ash是算术移位操作。所以(ash x -1)向右移动x一位,因此给出整数的一半。

答案 1 :(得分:3)

感谢Basile Starynkevitch对此问题的帮助......

无论如何,ash执行了arithmetic shift operation

(ash x -1)的情况下,它将x向右移动一位,最终返回整数的一半。

例如,考虑二进制数1101。二进制中的1101相当于十进制的13,可以这样计算:

8 * 1 = 8
4 * 1 = 4
2 * 0 = 0
1 * 1 = 1

8 + 4 + 0 + 1 = 13

运行(ash 13 -1)将查看13的二进制表示,并执行-1的算术移位,将所有位向右移位1.这将产生110的二进制输出(砍掉原始号码末尾的1。二进制中的110相当于十进制的6,可以这样计算:

4 * 1 = 4
2 * 1 = 2
1 * 0 = 0

4 + 2 + 0 = 6

现在,13除以2不等于6,它相当于6.5,但是,因为它将返回整数的一半,6是可接受的答案。

这是因为二进制是基础2。

答案 2 :(得分:0)

  问: ash函数有什么作用?为什么通过传递给 big 和-1的 small 参数?它是如何工作的?它对二进制搜索有什么作用?

它执行shifting bits的操作,更确切地说是Arithmetic shifting的操作,如针对Lisp的特定情况以图形方式解释/表示的:

> (ash 51 1)
102

当您执行(ash 51 1)时,它会将51的二进制文件110011向着左侧移1位,并得到1100110,这会给您102以十进制表示。 (在this answer中说明了从二进制到十进制的转换过程)

enter image description here

在最正确的空白位置(称为 L S 重要的 B 0强>)。

> (ash 51 -1)
25

当您执行(ash 51 -1)时,它将二进制数51即110011右侧移动1位(负值代表相反的方向),结果为{ {1}}的十进制数为102。

enter image description here

在这里丢弃冗余LSB。

在《 Lasp of Lisp》中举例说明的“ guss-my-number”游戏,我们有兴趣将范围减半或求平均值。因此,11001将100 + 1 = 100/2减半得到50。我们可以按以下方式检查它:

(ash (+ *small* *big*) -1))

要注意的一件有趣的事是,您可以通过左移1位将整数的值翻倍,然后通过右移1位将其(大约)减半。