Once upon a time, I wanted to know what love was. Love is there if you want it to be. You just have to see that it’s wrapped in beauty and hidden away between the seconds of your life. If you don’t stop for a minute, you might miss it.
我想看看用 Common Lisp 怎么写插入法排序(我对语言本身还不熟悉,所以想看别人怎么写的),于是 Google “common lisp insertion sort”,来到了这里,LiteratePrograms,一个记录了很多程序的 Wiki,很不错的地方。看了一会儿就想也许 Fibonacci 数列的算法也会有,于是 Google “common lisp fibonacci”,这次同样也有 LiteratePrograms 上面的文章出现在结果中,不过位置比较靠后,而且上面的算法也很普通。第三个结果来自 CLiki,文章在这里,这里的算法除了那个 generator 以外我在上一篇文章里面都有给出,包括那两个 Θ(lg(n)) 的算法。而最后在 LiteratePrograms 上逛的时候又看到了一个用矩阵乘法的算法。
利用 generator 来求 Fibonacci 数列
利用 generator 的算法比较特别,有点像 continuation。看过 Wikipedia 的解释以后才知道什么是 generator,而 continuation 可以用来实现 generator。代码如下:
(let ((a 0)
(b 1))
(defun fib ()
(prog1 a (psetf a b b (+ a b)))))
这里的实现使用了 closure,let 返回了一个函数 fib,fib 中使用到的 a, b 在 let 创建的环境中,每一次调用 fib 都会返回 Fibonacci 数列中的下一个值,并且更新环境中的 a, b。prog1 对第一个 form 求值,然后对后面的 form 进行求值,最后返回第一个 form 的值。而 psetf 在赋值之前对所有的需要求值的 form 进行求值,然后在赋值,这样就避免了要使用一个变量来记录 a 的值的需要。
(defunfibonacci-rec-2(n)(cond((=n0)0)(t(multiple-value-bind(x)(fib-twon)x))));; Returns the n'th and n-1'th fibonacci number.(defunfib-two(n)(cond((=n1)(values10))((evenpn)(multiple-value-bind(ii-1)(fib-two(/n2))(values(*i(+i(*2i-1)))(+(*i-1i-1)(*ii)))))(t(multiple-value-bind(ii-1)(fib-two(/(-n1)2))(values(+(*ii)(expt(+i-1i)2))(*i(+i(*2i-1))))))))
考虑之前提到的 T 变换(不是递归式里面的 T),实际上求 F(n) 就是对最初的数值做 n 次 T 变换。
F(n) = T(T(T(...T(1, 0)))) = T^n(1, 0)
改变迭代过程的思路其实使用下面的关系式求乘方是一样的:
a^n = (a^2)^{n/2} = (a^4)^{n/4} = ... = (a^n)^1
具体算法实现的时候,当 n 不是偶数的时老老实实多乘一个 a,是偶数的话就平方。对 Fibonacci 数列,我们希望能够找到一个变换序列 {T_i}(下划线表示下标),使得:
T_1(a, b) = T^2(a, b)
T_2(a, b) = T^4(a, b)
T_3(a, b) = T^8(a, b)
...
T_{k-1}(a, b) = T^{n/2}(a, b)
T_k(a, b) = T^n(a, b)
对任意的 i,下式成立:
T_{i+1}(a, b) = T_i^2(a, b)
SICP 上面用的办法是定义 T{pq}(a, b) = (bp + aq + ap, bp + aq),然后寻找变换 T{p’q’},使得:
…
Laws (like copyright law) and legal issues, on the other hand, are fundamentally *not* about “personal” things, they are about interactions that are *not* personal. So laws need to be fundamentally different from morals. A law has to take into account that different people have different moral background, and a law has to be _pragmatic_. So trying to mix up a moral argument with a legal one is a fundamental mistake. They have two totally different and separate areas.
The GPLv2 is a *legal* license. It’s not a “moral license” or a “spiritual guide”. Its raison-d’etre is that pragmatic area where different peoples different moral rules meet. In contrast, a persons *choice* to use the GPLv2 is his private choice. Totally different. My choice of the GPLv2 doesn’t say anything about my choice of laws or legal issues.
…
Science is what we understand well enough to explain to a computer. Art is everything else we do.
…
Science advances whenever an Art becomes a Science. And the state of the Art advances too, because people always leap into new territory once they have understood more about the old. This book will help you reach new frontiers.
mysql 命令行客户端默认使用的字符集也是 latin1,如果你通过这个来插入中文的话也会出现乱码的情况。解决的办法是执行语句 set names ‘utf8’ 来告诉服务器使用 UTF-8 编码来和客户端通信。你也可以使用 set charset ‘utf8’,它和 set names 区别只在于 collation 上。set names 和 set charset 都相当于执行了三条语句,具体的内容可以去看 mysql 文档 10.4 节。我想这个方法在使用 jdbc 的时候也是可以的,所以如果 jdbc 的指定数据库地址中没有告知使用的字符集编码的话可以通过执行上面的语句来达到相同的效果。