2009年7月30日星期四

为什么你不应该在键盘和鼠标上吝啬

在我的个人电脑上(Windows系统)装了一个叫WinOMeter的小东西,它可以统计你的键盘击键次数、鼠标击键次数以及鼠标移动的里程。我也不记得是怎么装上了这个东西,可能是从小众软件看到的吧。它在我的系统里从三月二十四号开始静悄悄的运行着,到现在已经有四个月了。这四个月我都干了什么?看看数据就知道了:

键盘敲击总数:1159010
键盘敲击接近116万次。我在上班的时候一般把这台笔记本打开,扔在一边,让它开着QQ接收一些个人信息放个歌啥的,总之很少动它。下班的时候一般会看在上面看看网页啥的。即使这样,在四个月中,它接受的键盘敲击仍然超过100万次。我在工作机上要写程序,对键盘的操作至少是对这台笔记本的五倍以上。可以想象,这四个月中我对键盘的敲击肯定超过了500万次!

鼠标移动总里程:79.444526km
我对鼠标的需求是很少的,两台机器上都几乎只使用Firefox(Vimperator)和终端(putty)。即使这样,鼠标同志也很辛苦,四个月跑了接近80公里。普通的Windows用户的鼠标肯定要比我的鼠标不幸的多,承受的压力更大,跑的路应该是我的五倍以上,即80*2*5=800km!

鼠标点击(左中右):427878,168458,162137
这里面有一部分的功劳是Starcraft的。

开机时长:81d
三月二十四日到现在一共才98天,这台本本的运行时间达到了81天,我是不是对它太残酷了……其实我“基本上”每天晚上都关机的……这样算下来它平均每天的休息时间大概是(98-81)*24/98~=4.16个小时。我不喜欢睡觉,它也跟着倒霉。城门失火,殃及池鱼啊。

这就是我愿为键盘鼠标花一千块钱的原因。

2009年7月29日星期三

Cheat-Sheet for Vimperator

今天看到一个有意思的网站www.cheat-sheets.org,在上面找到了Vimperator的cheat-sheet,竟然还有三种。

中间的一张最传统,我也最喜欢:http://vi.shiar.net/vimperator(它竟然不是图片!)

2009年7月21日星期二

SICP 第一章

大四的时候就听说《Structure and Interpretation of Computer Programs》这本书很不错,但一直没有时间拿来看看。正巧一个同事正在看这本书,于是我也来凑个热闹,大家可以一起讨论,不亦乐乎?

习题程序:http://files.getdropbox.com/u/1584769/chapter1.tar

1.5
(test 0 (p))
使用应用序求值时,会先对参数进行求值,即将这个表达式中的(p)展开为(p),然后就死循环了,根本没有计算if表达式谓词的机会。

1.6
错:把if替换成为new-if之后就不是尾递归了,然后就堆栈溢出了
对:解释器的对于用户自定义函数的解释方式是应用序的,new-if也不能例外。
这样的后果就是new-if在被展开之前,它的参数就需要被计算,然后就死循环了。

1.7
试了一下,精度是16位。使用原有的good-enough?函数会出现的问题是当根的值达到16位这个极限的时候出现溢出。
当n很大的时候,根的平方减去n之后得到的是负数,那肯定小于给定的阈值咯。
使用新的good-enough?之后,对于很大的数和很小的数也能得出一个平方根的近似值。
当阈值(波动幅度)小于0.1%时,这个根的平方减去n的差值和n的比值大概在e-5这个数量级。

1.9
(define (+ a b)
(if (= a 0)
b
(inc (+ (dec a) b)))
)
(+ 4 5)的执行过程应该是这样的:
- (+ 4 5)
- (if (= 4 0)
- 5
- (inc (+ (dec 4) 5)))
- (inc (+ (dec 4) 5))
- (inc (+ 3 5))
- (inc (if (= 3 0)
- 5
- (inc (+ (dec 3) 5))))
- (inc (inc (+ (dec 3) 5)))
- (inc (inc (+ 2 5)))
- .
- .
- .
- (inc (inc (inc (inc (+ 0 5)))))
- (inc (inc (inc (inc 5))))
- (inc (inc (inc 6)))
- (inc (inc 7))
- (inc 8)
- 9
递归

(define (+ a b)
(if (= a 0)
b
(+ (dec a) (inc b))))
(+ 4 5)的执行过程应该是这样的:
- (+ 4 5)
- (if (= 4 0)
- 5
- (+ (dec 4) (inc 5)))
- (+ (dec 4) (inc 5))
- (+ 3 6)
- ...
- (+ 2 7)
- ...
- (+ 1 8)
- ...
- (+ 0 9)
- 9
迭代

1.10
(define (f n) (A 0 n)) == (f(x, y) = 2y)
(define (g n) (A 1 n)) == (g(x, y) = 2^y)
(define (h n) (A 2 n)) == (h(x, y) = 2^2^... (n次))

1.20
应用序:
(gcd 206 40)
(gcd 40 (remainder 206 40))
(gcd 40 6)
(gcd 6 (remainder 40 6))
(gcd 6 4)
(gcd 4 (remainder 6 4))
(gcd 4 2)
(gcd 2 (remainder 4 2))
(gcd 2 0)
remainder执行了4次

正则序:
(gcd 206 40)
(gcd 40 (remainder 206 40)) ; gcd(40 6)
(if (= (remainder 206 40) 0) ; +1
40
(gcd (remainder 206 40) (remainder (remainder 206 40) 40)))
(gcd (remainder 206 40) (remainder (remainder 206 40) 40)) ; gcd(6 4)
(if (= (remainder (remainder 206 40) 40)) ; +2
(remainder 206 40)
(gcd (remainder (206 40) 40) (remainder (remainder 206 40) (remainder (remainder 206 40) 40))))
(gcd (remainder (206 40) 40) (remainder (remainder 206 40) (remainder (remainder 206 40) 40))) ; gcd (4 2)
(if (= 0 (remainder (remainder 206 40) (remainder (remainder 206 40) 40))) ; +4
(remainder (206 40) 40)
(gcd (remainder (remainder 206 40) (remainder (remainder 206 40) 40))
(remainder (remainder (remainder 206 40) (remainder (remainder 206 40) 40)) (remainder (remainder 206 40) 40))))
(gcd (remainder (remainder 206 40) (remainder (remainder 206 40) 40))
(remainder (remainder (remainder 206 40) (remainder (remainder 206 40) 40)) (remainder (remainder 206 40) 40)) ; gcd(2 0)
(if (= 0 (remainder (remainder (remainder 206 40) (remainder (remainder 206 40) 40)) (remainder (remainder 206 40) 40))) ; +7
(remainder (remainder 206 40) (remainder (remainder 206 40) 40)) ; +4
(gcd (remainder (remainder (remainder 206 40) (remainder (remainder 206 40) 40)) (remainder (remainder 206 40) 40))
(remainder (remainder (remainder 206 40) (remainder (remainder 206 40) 40))
(remainder (remainder (remainder 206 40) (remainder (remainder 206 40) 40)) (remainder (remainder 206 40) 40)))))
remainder执行了18次

1.21 - 1.28
由于guile的current-time只能精确到秒,程序无法得到实际运行的时间(只能得到0)。因此,这几个习题可能今后使用clisp或者MIT Scheme来实现。

1.34
(f, f)
-> (f, 2)
-> (2, 2)
出错:Wrong type to apply
把一个常数当作一个函数使用

1.36
启动数值a
a = 2.0时
不用平均阻尼:40步
使用平均阻尼:37步
a = 10.0时
不用平均阻尼:39步
使用平均阻尼:38步
a = 100.0时
不用平均阻尼:42步
使用平均阻尼:42步
a = 500.0时
不用平均阻尼:43步
使用平均阻尼:44步

1.37
a)和b)的解法都是偷懒的,因为D和N都等于1。这种办法到1.38就不行了。

1.41
(double)从表面上看是x2的关系,实际上是^2的关系,这从代码中可以看出来。
(define (double f)
(lambda (x) (f (f x))))
函数f第二次作用的对象是第一次作用的结果。
因此,由于(double double)函数的意义是将参数函数应用四次,那么当(double double)的参数是自身的时候,那就是4x4=16次了。

1.45
题目要求导出计算n次方根时使用平均阻尼的一般规律,可惜我没做出来。
在求五次方根时,两次平均阻尼虽然可以收敛,但是结果不正确。显然,收敛的方向出现了偏差。
求更加高次方根时,两次平均阻尼竟然都可以收敛,但是结果均不正确。
赶时间,没有仔细做下去。以后也许有机会。

2009年7月9日星期四

Chrome OS

Google终于亮出了底牌,遮遮掩掩许久之后才宣布Chrome会变成一个操作系统。半年多前和lvscar等几个同事争论的话题今天变成了事实。Firefox,你能赶上这班车么?

ChromeOS的消息只是宣布而已,并没有多少实质性的内容放出。不过就这个消息已经足以引起大家的联想了。在浏览器取代桌面的这种趋势之下:
1、国内那些各种定制的山寨浏览器之流,你们的生存空间在哪里?傻眼了吧?
2、Linux下的应用会空前繁荣,输入法、显卡驱动、网卡驱动等等这些基础问题看到了解决的曙光。

Chrome之下的新的"windowing system"也是很让人期待的一个东西。X的构架从1987年以来就没有发生大的变化,总该引入点竞争了:)

2009年7月5日星期日

Search Marker plugin for Vimperator

Vimperator是个非常棒的Firefox扩展,但是我一直希望它能在搜索页面的时候能够和Search Marker或者XUL/Migemo一样,在页面右侧显示一个标记栏。很可惜的是这两个扩展和Vimperator都不兼容。既然没有人为Vimperator写这么一个插件,咱们就自己动手吧:)

插件下载地址:http://www.mozdev.org/pipermail/vimperator/attachments/20090705/6df4ab76/attachment.js

这个插件的大部分代码都是直接从Search Marker里拿过来的,经过了简单的修改。XUL/Migemo的效果太炫了,我不想把事情弄的很复杂,因为Vimperator本身就已经很复杂了。Search Marker看起来很不错,但是缺少了一样东西,那就是在高亮了所有搜索结果之后在右侧的标记栏中显示用户当前选中的搜索结果。幸好定位用户选中的文字在Firefox中还是很简单的。

Vimperator修改了Firefox内部的很多东西,例如这里的页面搜索。这使得它的排他性变得非常强烈,幸好Vimperator足够强大。不过话说回来,在自我封闭性上Vimperator还真是和Vim一脉相承。在这一点上我更加喜欢Emacs,虽然我不是很会用。难道是Vim的行为模式注定了它在设计和代码层面上就必须这么封闭么?有时间的话我希望去看看Emacs的结构,看看Lisp是如何将一个编辑器变成一个操作系统的。