5

所以,我现在正在阅读《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?它是如何工作的?它对二分搜索有什么作用?

4

3 回答 3

3

感谢Basile Starynkevitch提供的帮助...

无论如何,ash执行算术移位操作

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

例如,考虑二进制数11011101二进制等价13于十进制,可以这样计算:

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

8 + 4 + 0 + 1 = 13

运行(ash 13 -1)将查看 13 的二进制表示,并执行 -1 的算术移位,将所有位向右移动 1。这将产生二进制输出1101在原始数字的末尾截去)。110二进制等价6于十进制,可以这样计算:

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

4 + 2 + 0 = 6

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

这是因为二进制是以 2 为底的。

于 2011-12-26T10:46:20.253 回答
3

谷歌为你提供了这个页面,它解释了这ash是一个算术移位操作。所以向右(ash x -1)移动x一位,所以给它的整数一半。

于 2011-12-26T10:23:35.623 回答
1

Q. ash 功能有什么作用?为什么传递small的参数加到big和-1?它是如何工作的?它对二分搜索有什么作用?

它执行移位操作,更准确地说是算术移位,如针对 Lisp 的特定情况以图形方式解释/表示的那样:

> (ash 51 1)
102

当你这样做时(ash 51 1),它会将 51 的二进制数向左侧110011移动 1 位,从而得到十进制的 102。(这个答案解释了二进制到十进制转换的过程)1100110

在此处输入图像描述

这里它在最右边的空白处添加(称为 LS显着B它)。0

> (ash 51 -1)
25

当你这样做时(ash 51 -1),它会将 51 的二进制数移动 1 位,即向右110011移动1 位(负值代表相反的方向),结果是十进制的 102。11001

在此处输入图像描述

在这里,它丢弃了多余的 LSB。

在 Lisp 中说明的“猜我的数字”游戏的特定示例中,我们对将范围减半或平均感兴趣。因此,(ash (+ *small* *big*) -1))将 100+1 = 100 / 2 减半得到 50。我们可以检查如下:

> (defparameter *small* 1)
*SMALL*
> (defparameter *big* 100)
*BIG*
> 
(defun guess-my-number ()
    (ash (+ *small* *big*) -1))
GUESS-MY-NUMBER
> (guess-my-number)
50

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

于 2019-05-14T16:08:16.623 回答