留学德国之注意事项

xiaoyong Post in 生活,Tags: , , ,785 views
1

今年 6 月,我有幸到德国交流。虽然只有短短一个多月,却感触良多。在德国的时候就想写这篇文章了,可惜一直懒于动笔。过几天好多同学也要去德国了,所以先写下《注意事项》篇,希望对他们以及第一次去德国的朋友有所帮助。

免责声明:在此给出的信息和建议并不保证 100% 准确,且不一定适用于德国所有地区,仅供参考。惹了麻烦别找我 :-)

一、出国前的准备,主要说一下要带的东西。

必须带的东西

  • 钱和电源转接头。有了钱就可以换取其它物品,衣食住行都不愁。可以用欧元现金,也可以刷信用卡。Visa 和 MasterCard 都可以用;如果你运气好,找到印有中国银联标记的刷卡机器,那么银联卡也是可以刷的,反正我是没找到过 — 有了电源转接头才可以为你的电脑、相机等提供动力,否则只能歇菜了~ 因为中国的插头和德国的插座不匹配。我是从这家淘宝店买的,经验证可用。数量的话看你的电器了,一般 2 个就够用了,再不够的话可以带个接线板过去。

推荐带的东西

  • 要紧的生活用品,如毛巾、牙刷、牙膏、洗发水、肥皂、拖鞋等到德国当天就用到的东西。在当地当然也可以买到它们,不过刚到德国,你得忙于办手续、熟悉环境。就算有空闲的时间,你也不一定找得到超市;就算找到了超市,你也不一定能找到你想要的物品(特别是假如你不懂德语的话)。而且一般来说,在德国买要比中国买贵一些。所以为了让你的第一天在德生活舒适些,还是带上这些吧,越全越好。注意上飞机时牙膏等液态的东西不让随身携带,托运就好了。
  • 适量的衣物,这个后面还会提到。
  • 电器,笔记本、相机、手机等。最好事先在手机上装上德语词典,如果你不懂德语,这个会非常有用。
  • 中国的食物。德国的食物比我们的简单,可以带上一些辣酱等调味品,注意液体要托运。
  • 其它自己特别需要的东西。

二、衣食住行游

德国的纬度比较高,气温相比上海要低一些。夏天很凉爽,晴天气温大概二十多度,雨天只有十几度,穿短袖还嫌冷,所以最好带上外套和长裤。冬天的时候应该比上海要冷一些,多带点保暖的衣服。
在德国买衣服怎么样?这个我不太清楚,我只买过一件 9.99 欧的牛仔裤,算起来和国内的价格差不多(说不定是 made in China~)。Adidas 的鞋子有看到四五十欧的,也许比国内买要便宜一些。

德国的大学也有餐厅,不过奇怪的是只供应午餐,不提供早餐和晚餐(至少我去的那个大学是这样的)。早餐一般吃面包+牛奶,晚餐一般自己做。超市里米油盐蔬菜肉一应俱全,guest house 里都有厨房,自己做饭很方便。厨房里装的不是煤气灶,而是电炉灶,有点像电饭锅里用的加热板,用习惯了还觉得挺好用的,安全又环保。如果图方便,可以吃汉堡、牛排、皮萨等。
如果周末出去游玩,可以自己带几片面包,或者在火车站买个汉堡充饥。德国人挺厚道的,火车站里的东西卖得不比其它地方贵,不像我们这儿。
总体来说,德国超市里卖得东西比国内的贵,不过有两样东西是例外:牛奶和巧克力,在那可以狂吃 — 如果你为了省钱,总挑便宜货,那么你会发现你将买到很多 ja! 牌的商品。ja! 牌什么产品都有,米、牛奶、鸡蛋、香肠、面包等等。

我们住的是学校的 guest house,条件算比较好的,月租费据说也挺贵的。因为学校给安排好的,所以没去了解租房的行情,也不说什么了。

德国的铁路还是挺发达的,不过票务系统也是挺复杂的。据我不完全了解,主要有两套系统,一是全国性的 DB,可以乘坐跨越城市或者跨越州的快车(ICE/IC 等)或慢车(RE/RB 等),二是地方公交系统,包括地铁、公共汽车、电车,只能在市内运行。所有车票可以在自动售票机上买到,每个车站都配有自动售票机。如果你想在周末出游,那么天票是很合算的选择。天票种类的介绍以及自动售票机的使用请参考穷游网上的这篇帖子。最重要的查询交通信息的网站是 DB 官网,在这可以查到所有车次的详细信息(在哪转车,在哪个站台候车等),包括 DB 和地方公交。
火车票可以提前 3 个月买,而且他们没有卖完票的概念,完全可以临时买。不过 DB 的票(特别是快车)如果提前买,通常会有很大幅度的优惠。买到票后,坐车的方式和中国是不一样的。仰仗德国国民的高度自觉,他们进站行李不需要安检,也不需要检票,直接上车就可以了。你可以耍小聪明逃票,不过一定几率会有人查票,被查到的话要扣信用、罚款,所以建议最好不要这么干 –
DB 的火车站有好多个站台(Gleis,请记住这个单词),查好要坐的车在哪个站台停,然后去那儿等着就可以了。不要以为德国人严谨,火车就会很准时,出现晚点千万不要觉得吃惊~ 候车的时候,还要注意,德国的火车车身上可能不会贴着车次信息,而是这条火车线路的编号。所以看到车上写的编号和车次不同,也不用觉得惊奇~ 站台上会有电子屏幕,显示下一辆车的信息,以那个为准。
坐地铁的时候,在进站前需要给地铁票打票。每一个地铁站入口处都有一个打票机,把票塞进一个插槽里,然后机器会票的边边上打印一行信息,包括打票的时间等。打印上时间是因为一张车票不限制你要去的目的地站点,而是限制你能乘坐的时间间隔。比如你买了一个半小时的票,就是在打票后一个半小时内,你可以任意地乘坐地铁,不管你要去哪里,也可以多次乘坐。要注意的是时间间隔算的是下车时间,不是上车时间,也就是超时后你就必须下车,不能再待在车上了。不过这个也不是绝对的,各个州的政策可能会不一样。波鸿地铁是这样的,但是波恩的又不一样。在波恩,票是根据你要去的目的地站点买的,所以不限时间,也就不用打票。地铁站台上都会有一个信息公告栏,那上面会有各种票的介绍,以那个为准。

熟悉了交通系统后,出游是很方便的。德国有个好处,就是城市都很小(一般只有几十万人口,上百万的就算大城市了),而且城与城之间离得很近,一条线过去,就可以玩很多个城市了。在市区,教堂是一道难以忽视的风景。一座城市往往有很多座教堂,矗立在各个城区,蔚为壮观。在波鸿市区有一处公园,草坪上一群一群的兔子,人靠得很近都不怕。公园里有很多人在遛狗,狗看到兔子就去追,不过一般都追不到的 — 不得不让人感慨:这才叫真的和谐!在郊区,房子大多是别墅,门口都带了一块花园,里面种着花花草草。而且他们的房子造型各异,颜色多样,不像我们这边的房子,都是照一个模子刻出来。德国有很多博物馆,一般是收费的。在外面想解手怎么办?火车站、旅游景点附近通常有公厕,不过都是收费的,有收 50 分的,60 分的,还有 1 欧的。因为是投币的,所以需要准备好零钱。
如果你想出国游,推荐一个网站:汉升旅游,组团旅游用的。在对德国不是很熟的情况下,跟团出游是个很好的选择,而且费用相对较低。(此网站是张韬兄向我们推荐的。)

三、杂项

网购

他们用 eBay,类似于我们的淘宝,还有一些 b2c 商城(Amazon?),一些公司的官网上也支持在线购买。支付可以用 PayPal,我没办过,所以也没网购过。具体情况,像选什么快递公司啦什么的就不了解了。

寄信

现在写信比较少,不过寄明信片还是比较流行的。寄信的时候,收件人地址可以用中文(因为信到国内以后就是国内的邮递员帮忙送达了),只要在地址前加上 “P.R. China” 就可以了。寄到国内邮费 1 欧。在邮局有一个自动售邮票的机器,有趣的是邮票是临时打印的,而且多少面值都可以,你可以买一张一分钱的邮票 — 邮票背面是特殊材料做的,一沾水就有粘性,用不着胶水,很方便。

语言

德国人虽然也学英语,不过主要还是用的德语。德国的电视节目,就算是外语电影,也全部是德语配音,而且一般都没有字幕。我还看过周星驰的《功夫》呢,也是德语配音~ 火车上报站用的也是德语,只有在像法兰克福、杜塞尔多夫这种大城市/州府所在地才会报英语。更加“无耻”的是,一列火车经过这类大城市的时候,会报英语,到达下一个小城市,就只用德语了。。。学生和老师一般都会说英语,不过普通老百姓却不一定,尤其是在小地方。有时候你想问路,或者被问路,听到对方说德语该怎么办?没关系,你可以这样回应:”Sorry, can you speak English?”,还可以碰碰运气这样问:“请问你会说汉语吗?” ==

上网

大家都知道中国建了一堵墙,以防止广大网民知道得太多。德国曾经也有一道墙,用来阻止社会主义国民逃往资本主义国家,不过早在 20 多年前就已经被推倒了。德国不怕自己的国民知道得太多,至少不怕他们用 Google 搜索知识,用 Gmail 交流感情、用 Twitter 咆哮生活感触、用 Facebook 交友。我们在那儿自然可以沾他们的光,了解一些“不该”了解的东西。
在德国用 P2P 下载是违法的,据说曾经有人因为非法下载/上传被起诉,吓得我们不敢用 BT、电驴。谨慎起见,建议你也不要用了,少看点片,多搞点科研~

过马路

过马路也有讲究?是的。假设你在一个十字路口,等着红灯变绿灯好过马路。可是你等了好久,发现红灯一直没变绿,怎么回事呢?原来旁边有一个按钮,你得按一下,红绿灯才知道有人要过马路,才会变成绿灯。也就是说,他们的红绿灯切换时间不是固定的,而是动态调整的,在有需要时才会变颜色。厉害吧~ 这样可以提高效率,特别是在行人稀少的地方。

四、致谢

出国前特别受到张韬兄和国锋师兄的指点,没有他们的指点,我的德国之旅肯定会艰难很多。在国外,受到老板 Axel 很多帮助,还有在那边的留学生 Lin Jie 也给了很多帮助。还有跟我同去的杨晨,这里有很多东西是我俩共同琢磨出来的。在此一并表示感谢!

预告:下一篇文章的题目叫《留学德国之德国印象》,敬请期待~

我们要听立体声

xiaoyong Post in 生活,Tags: , , ,1,532 views
3

猛然发现,上一次更新此博客已经是 5 个月前的事了。5 个月可以让良田都变荒地了。原因有二,一是越来越慵懒,二是越来越淡定了。每当有表达欲望的时候,想到自己的这些想法于他人,于世界都几乎不会有什么影响,也就罢了,自己感受过就好了,更况且有比博客更加快捷方便的 Twitter 存在。不过让我感动的是,博客的订阅数竟然一直在增加。谢谢大家的支持,以后我会勤快些,多分享好玩、有趣的事物的。

本文的话题与声音有关。先介绍一些背景知识。大家知道,健康人都有两只耳朵。如果周围有一处声源,由于相对于声源的距离和方向略有不同,它们接收到的声音信号的强度和时间就会不同。人体整合来自两耳的信息,就能判断声源在空间中的方位。耳机被发明之初,考虑到了人有两只耳朵(所以有两个扬声器),但没有考虑到两耳可以接收不同声音的功能(所以早期的声音是单声道的)。随着科技进步,立体声 (Stereo) 被发明了。立体声有左右双声道,分别模拟自然状态下左右耳接收到的信号。左右声道的声音分别从耳机的左右扬声器中发出,这样就有了立体声的效果了。当然,现在人们已经不再满足于双声道,而是追求多声道环绕立体声了。不过对于普通耳机来说,双声道就足够了。

前面都是废话,我遇到并想要解决的问题是:在特殊环境下如何分辨耳机的左右声道?一般耳机上都会标上 L/R 来区分,可是如果我想在黑暗环境中听音乐,或者耳机用久了,字符被磨掉了怎么办?你说随便猜一下呗,况且一般人就算戴反了也听不出差别来。可是像我这样有洁癖的是不能容忍这种错误的,就算它真没有什么危害。。。还有一种情况,如果你在打类 CS 的游戏,你需要通过声音来判断敌人的方位,这时候如果左右耳戴反了你就死定了 ==

本以为需要写程序的,后来发现只要制作一段音频就可以了。这段音频也是双声道的,它的声音分成两小段,一小段只从左声道发声,另一小段只从右声道发声。这样的话迷茫的时候,只需听一下这段声音,就能区分耳机左右声道了。制作工具是开源软件 Audacity,以下是它的使用界面:

Audacity

其中加载的正是我制作完成的音频。图中两组波谱分别对应左右声道的声音信号,可以看到左右声道的声音是错开播放的。

最后附上这段音频,里面有 xiaoyong 真人发音,欢迎指正 ~~

音频片段:需要 Adobe Flash Player(9 或以上版本)播放音频片段。 点击这里下载最新版本。您需要开启浏览器的 JavaScript 支持。

下载地址:left_right_denoised

这些名字你都念对了吗?

xiaoyong Post in 技术,Tags: , ,1,846 views
2

温馨提示:在念对以下名字之前,请不要自称 “Geek”, “UNIX/Linux Guru”, “开源爱好者”之类。如果你喜欢一个女孩,却总是在她身前/背后念错她的名字,你是不会也不配得到她的芳心的。所以,喜欢她,就从念对她的名字做起吧 -:)

说明:

  1. 以下列出的读音均使用国际音标表示,如果你对它们感到陌生,请阅读维基百科上的解释
  2. 读音标准主要来自维基百科词条,部分来自词典。

1. 操作系统类

  • Mac OS X: /ˈmæk ˌoʊ ˌɛs ˈtɛn/(最后那个 X 指的是罗马数字 10)
  • Linux: /ˈlɪnəks/ in American English, /ˈlɪnʊks/ in Europe and Canada(我老板念第二个,我喜欢念第一个)
  • GNU: /ˈɡnuː/
  • Debian: /ˈdɛbiən/
  • Knoppix: /kˈnɒpɪks/
  • Ubuntu: /uːˈbuːntuː/(这个估计很多人要抗议了,不过 Ubuntu 的创始人就念这个)
  • Kubuntu: /kuːˈbuːntuː/
  • Xubuntu: /zuːˈbuːntuː/
  • Lubuntu: /luːˈbuːntuː/
  • Fedora: /fɨˈdɔrə/
  • openSUSE: /ˌoʊpənˈsuːzə/
  • SUSE: /ˈsuːsə/
  • Arch: /ˈɑrtʃ/
  • Gentoo: /ˈdʒɛntuː/
  • Sabayon: /sɑ:bɑ:’juŋ/

2. 编程语言类

  • C: /ˈsiː/
  • C++: /ˌsiː plʌs ˈplʌs/(不是 C 加加)
  • C#: “see sharp”
  • Java: /’dʒɑ:və/
  • Perl: /pə:l/ (the same to pearl)
  • Ruby: /ˈru:bi/
  • Python: [英] [ˈpaɪˌθɔn, -θən] [美] [ˈpaɪˌθɑn, -θən]
  • Bash: /bæʃ/
  • Javascript: /’dʒævə’skript/
  • Qt: officially as cute /ˈkjuːt/ but commonly as Q.T. /ˌkjuːˈtiː/ (Qt is cute)
  • Tcl: “tickle” or “tee-see-ell”
  • SQL: officially as /ˌɛskjuːˈɛl/ like “S-Q-L” but often as /ˈsiːkwəl/ like “sequel”
  • MySQL: officially pronounced /maɪˌɛskjuːˈɛl/ (“My S-Q-L”), but is often also pronounced /maɪˈsiːkwəl/ (“My Sequel”)
  • PostgreSQL: /ˈpoʊstɡrɛs ˌkjuː ˈɛl/

3. 文本编辑器

  • vi: /ˈviːˈaɪ/, much less commonly, /vaɪ/
  • Vim: /vim/
  • Emacs: /ˈiːmæks/

4. 桌面环境

  • GNOME: /ɡˈnoʊm/
  • KDE: /ˌkeɪdiːˈiː/
  • Xfce: pronounced as four individual letters

5. Misc

  • TeX: /tɛk/
  • LaTeX: /ˈleɪtɛk/, /ˈleɪtɛx/, /ˈlɑːtɛx/, or /ˈlɑːtɛk/(此处 [x] 不念 /ks/,而是介于 [k] 和 [h] 之间的一个音,不信看这个词条。Dress 老爷爷就念这个,你我不会念的就老老实实念 [k] 吧。)
  • daemon: /’di:mən/
  • IBus: pronounced as I-Bus

几种编程语言运行效率的粗略比较

xiaoyong Post in 技术,Tags: , , , , , , ,1,709 views
4

本文通过计算 Fibonacci 数列来比较几种编程语言的运行效率,包括常见的 3 类编程语言:编译性语言(C++),解释性语言(Perl, Python, Ruby)和脚本语言(Bash)。Fibonacci 数列有多种算法,这里使用的是递归法。

说明:各种语言各有所长,对不同的操作效率不尽相同。这里只看了一种情况,是极为粗略的比较,权当娱乐了 ~~

程序运行环境:

CPU: Intel T2350
Memory: 1GB
OS: Fedora 14
Linux Kernel: 2.6.35.6-48.fc14.i686

各种编译器 / 解释器版本信息(本人比较关注 Ruby,所以评测了两个版本的 Ruby 解释器):

gcc version 4.5.1 20100924 (Red Hat 4.5.1-4) (GCC)
perl 5, version 12, subversion 2 (v5.12.2) built for i386-linux-thread-multi
Python 2.7 (r27:82500, Sep 16 2010, 18:03:06)
ruby 1.8.7 (2010-08-16 patchlevel 302) [i386-linux]
ruby 1.9.2p35 (2010-11-02 revision 29665) [i686-linux]
GNU bash, version 4.1.7(1)-release (i386-redhat-linux-gnu)

程序代码如下:
C++版(fibonacci.cpp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <cstdlib>
 
int fibonacci(int i) {
    if (i <= 1) {
        return i;
    } else {
        return fibonacci(i-1) + fibonacci(i-2);
    }
}
 
int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " number" << std::endl;
    } else {
        int n = atoi(argv[1]);
        std::cout << "F(" << n << ") = " << fibonacci(n) << std::endl;
    }
    return 0;
}

Perl 版(fibonacci.pl)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/perl
use strict;
 
sub fibonacci {
    my $i = shift;
    return $i if $i <= 1;
    return fibonacci($i-1) + fibonacci($i-2) if $i > 1;
}
 
if (@ARGV < 1) {
    print STDERR "Usage: $0 number\n";
} else {
    my $n = shift @ARGV;
    print "F($n) = ", fibonacci($n), "\n";
}

Python 版(fibonacci.py)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python
import sys
 
def fibonacci(i):
    if i <= 1:
        return i
    else:
        return fibonacci(i-1) + fibonacci(i-2)
 
if len(sys.argv) < 2:
    print "Usage: %s number" % sys.argv[0]
else:
    n = int(sys.argv[1])
    print "F(%d) = %d" % (n, fibonacci(n))

Ruby 版(fibonacci.rb)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/ruby
 
def fibonacci(i)
    if i <= 1
        return i
    else
        return fibonacci(i-1) + fibonacci(i-2)
    end
end
 
if ARGV.length < 1
    puts "Usage: #{$0} number"
else
    n = ARGV[0].to_i
    puts "F(#{n}) = #{fibonacci(n)}"
end

Bash 版(fibonacci.sh)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
 
function fibonacci {
    i=$1
    if [ $i -le 1 ]; then
        echo "$1"
    else
        (( --i ))
        first=$( fibonacci $i )
        (( --i ))
        second=$( fibonacci $i )
        echo $(( first + second ))
    fi
}
 
if [ -z $1 ]; then
    echo "Usage: $0 number"
else
    result=$( fibonacci $1 )
    echo "F($1) = $result"
fi

主程序用 Ruby,使用 Gruff 模块来画图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/ruby
require 'rubygems'
require 'gruff'
 
withBash = false # Flag to turn Bash on or off
if withBash
    $max = 20 # Maximum of n
else
    $max = 32
end
$timeOf = {}
 
# Method to profile time consuming
def profile desciption, &block
    time = []
    (2..$max).each do |n|
        next if (n % 2) != 0
        startTime = Time.now
        block.call(n)
        duration = Time.now - startTime
#        puts desciption + ": " + duration.to_s + " seconds"
        time.push(duration)
    end
    time
end
 
# Method to plot graph with Gruff
def gruffPlot(num, withBash)
    targets = ["C++", "Perl", "Ruby-1.8.7", "Ruby-1.9.2", "Python"]
    if withBash
        targets.push("Bash")
    end
 
    g = Gruff::Line.new
    g.title = "Time Consuming of Fibonacci Number in Several Programming Languages"
    g.title_font_size = 18
 
    targets.each do |language|
        g.data(language, $timeOf[language][0..(num/2-1)])
    end
 
    # Set labels of x-axis
    g.labels = {}
    (2..num).each do |i|
        if (i % 2) == 0 # Even number
            g.labels[i/2-1] = i.to_s
        end
    end
 
    g.x_axis_label = "n"
    g.y_axis_label = "Time (seconds)"
 
    if withBash
        filename = "graphWithBash_" + num.to_s + ".png"
    else
        filename = "graphNoBash_" + num.to_s + ".png" end
 
    g.write(filename)
end
 
$timeOf["C++"] = profile "C++ version" do |n|
    `./fibonacci_cpp #{n}`
end
$timeOf["Perl"] = profile "Perl version" do |n|
    `./fibonacci.pl #{n}`
end
$timeOf["Ruby-1.8.7"] = profile "Ruby-1.8.7 version" do |n|
    `./fibonacci.rb #{n}`
end
$timeOf["Ruby-1.9.2"] = profile "Ruby-1.9.2 version" do |n|
    `~/.rvm/rubies/ruby-1.9.2-head/bin/ruby ./fibonacci.rb #{n}`
end
$timeOf["Python"] = profile "Python version" do |n|
    `./fibonacci.py #{n}`
end
 
if withBash
    $timeOf["Bash"] = profile "Bash version" do |n|
        `./fibonacci.sh #{n}`
    end
    [12, 16, $max].each do |num|
        gruffPlot(num, true)
    end
else # No Bash
    [16, 24, $max].each do |num|
        gruffPlot(num, false)
    end
end
 
$timeOf.each do |key, val|
    puts key + ": " + val.join(" ")
end

在 n 取不同值下各个版本程序的运行时间(本来想用表格的,发现一行放不完,多行/转置太麻烦了,凑合着看吧 :-):

# No Bash (n = 2, 4, ..., 32)
C++: 0.014616 0.005932 0.006124 0.006147 0.006429 0.006814 0.008096 0.005878 0.007844 0.009254 0.009913 0.010877 0.015585 0.025772 0.026195 0.060132
Ruby-1.9.2: 0.025062 0.022758 0.017313 0.020393 0.020181 0.020269 0.020819 0.020977 0.025425 0.032843 0.026662 0.043297 0.081736 0.183789 0.456225 1.170084
Perl: 0.015518 0.016121 0.017061 0.017639 0.020361 0.019265 0.023919 0.025519 0.034577 0.052177 0.063214 0.143937 0.358551 0.90879 2.393584 6.134109
Python: 0.072047 0.064298 0.058883 0.058075 0.056147 0.058195 0.057439 0.057393 0.058493 0.069465 0.083222 0.109321 0.197521 0.415247 0.994579 2.503102
Ruby-1.8.7: 0.020334 0.012589 0.010816 0.01228 0.013191 0.017026 0.023844 0.033048 0.05195 0.065379 0.138034 0.316718 0.798044 2.073424 5.383572 14.39978
 
# With Bash (n = 2, 4, ..., 20)
C++: 0.008331 0.003803 0.003619 0.003912 0.006395 0.006822 0.006398 0.006918 0.006765 0.007366
Ruby-1.9.2: 0.018158 0.017577 0.021608 0.023735 0.016365 0.019361 0.023855 0.024327 0.02903 0.032401
Perl: 0.016652 0.015514 0.014294 0.015016 0.015607 0.015555 0.017225 0.021482 0.032593 0.046648
Python: 0.078785 0.074991 0.065337 0.070789 0.073334 0.06341 0.064527 0.082283 0.077052 0.081154
Ruby-1.8.7: 0.02199 0.018868 0.024702 0.022364 0.02092 0.025425 0.029925 0.042073 0.052613 0.076533
Bash: 0.021872 0.027994 0.052569 0.112122 0.222159 0.71495 1.829128 4.942952 13.230605 34.971108

画出的图表如下:
1. 包括 Bash, n = 2, 4, …, 20

2. 包括 Bash, n = 2, 4, …, 12

从图中可以看到 Bash 的效率大大低于其它语言。为了能看出其它语言之间的差别,把 Bash 剔除之后重新画图,得到以下结果。
3. 剔除 Bash, n = 2, 4, …, 32

在 n 取值较大时,效率是 C++ >> Ruby-1.9.2 > Python > Perl > Ruby-1.8.7
4. 剔除 Bash, n = 2, 4, …, 24

缩小 n 之后,发现 Python 比其它几个都要慢一点。
5. 剔除 Bash, n = 2, 4, …, 16

看得更仔细一点。

总结:

  1. 运行效率上,编译性语言 >> 解释性语言 >> 脚本语言
  2. 解释性语言之间也有几倍的差别
  3. 随着计算量的增大,各种语言的表现不尽相同,比如 Ruby-1.8.7 一开始比其它解释性语言都要快,后来比它们都要慢
  4. 对同一种解释性语言来说,解释器的改进可以极大地提高运行效率

最后我要说:我们家 Ruby 不慢 :-)

文本处理之字符编码

xiaoyong Post in 技术,Tags: , ,1,014 views
0

相信每一个 Linux 用户都经历过汉字乱码的问题。通常从 Windows 上流出来的包含汉字的文本文件都采用 GB2312/GBK/GB18030(简体)或者 BIG5(繁体)编码。而从 Linux/UNIX/Mac 上流出来的则通常采用 UTF-8 编码。在用编辑器查看中文文本的时候,如果不能正确识别字符编码,就会出现乱码。

在得到一个中文文本文件之后,我们如何去判断/转换它的编码呢?有以下几种方法:

1. 试错法,也就是瞎猜。简体中文先猜 GBK;如果不是,则猜 UTF-8;再不对,还有可能是 UTF-16(日本动漫/娱乐节目的中文字幕经常用此编码)。繁体中文的猜测次序是:BIG5 => GBK => UTF-8 => UTF-16。

2. 借用工具法。Linux 下有 enca/enconv 这个很好用的工具。用这条命令来检测文件编码:

$ enca -L zh_CN filename

用这条命令把字符编码转换成 UTF-8:

$ enconv -L zh_CN -x UTF-8 filename

3. 如果你是一名 Vimer,那么可以在 .vimrc 中添加以下内容,下次用 Vim 打开文件的时候,它会自动探测编码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
" Multi-encoding setting {
	if has("multi_byte")
		"set bomb
		set fileencodings=ucs-bom,utf-8,cp936,big5,euc-jp,euc-kr,latin1
		" CJK environment detection and corresponding setting
		if v:lang =~ "^zh_CN"
			" Use cp936 to support GBK, euc-cn == gb2312
			set encoding=cp936
			set termencoding=cp936
			set fileencoding=cp936
		elseif v:lang =~ "^zh_TW"
			" cp950, big5 or euc-tw
			set encoding=big5
			set termencoding=big5
			set fileencoding=big5
		elseif v:lang =~ "^ko"
			" Copied from someone's dotfile, untested
			set encoding=euc-kr
			set termencoding=euc-kr
			set fileencoding=euc-kr
		elseif v:lang =~ "^ja_JP"
			" Copied from someone's dotfile, untested
			set encoding=euc-jp
			set termencoding=euc-jp
			set fileencoding=euc-jp
		endif
		" Detect UTF-8 locale, and replace CJK setting if needed
		if v:lang =~ "utf8$" || v:lang =~ "UTF-8$"
			set encoding=utf-8
			set termencoding=utf-8
			set fileencoding=utf-8
		endif
	else
		echoerr "Sorry, this version of (g)vim was not compiled with multi_byte"
	endif
" }

为了在 Vim 的状态栏实时地显示所编辑的文件编码,在 .vimrc 中添加:

set statusline=%t%m%r%h%w[%L][%{&ff}][%{(&fenc==\"\")?&enc:&fenc}]%y[%p%%][%04l,%04v]

其中红色部分即为显示编码的设置。效果见前面一篇文章

也可以在 Vim 中转换编码:在命令模式下,输入 :set fileencoding=utf8 (还可以是 cp936,即 GBK 以及其它)然后保存,即可把编码转换成 UTF-8。

文本处理之文件格式

xiaoyong Post in 技术,Tags: , ,1,745 views
2

我曾经天真地认为,纯文本格式是全宇宙最通用的格式,具有跨编辑器、跨操作系统、跨星球的优点。后来我才发现,要实现这些目标,必须克服两只拦路虎。一个是文件格式,一个是字符编码。本文讨论文件格式问题,后面一篇文章将讨论字符编码问题。

据说早期人们用打字机打字的时候,要用两个动作才能完成另起一行。一个是把滑动架移回首位(称为回车,<CR>),另一个是把纸上移一行(称为换行,<LF>)。后来计算机出现了,又后来各种操作系统出现了,它们在处理换行符上出现了分歧,DOS/Windows 采用了 <CR><LF> 两个字符来表示换行符,UNIX 采用了 <LF>,Mac 则采用了 <CR>。就是这些分歧,给用户带来了无尽的困扰。

举个例子,用这行命令可以在文本每一行的行首添加行号,并且通过 cat -A 把特殊字符都显示出来:

$ perl -ne '$i++; print "$i. $_";' sample.txt | cat -A

sample.txt 的内容为:

There're
more
than
one
lines
here.

如果 sample.txt 是 unix 格式的,那么得到的结果是:

1. There're$
2. more$
3. than$
4. one$
5. lines$
6. here.$

OK,这是我们想要的结果。如果是 dos 格式的,结果是:

1. There're^M$
2. more^M$
3. than^M$
4. one^M$
5. lines^M$
6. here.^M$

虽然多了一个奇怪的字符,但勉强能接受。而如果是 mac 格式的,结果则是:

1. There're^Mmore^Mthan^Mone^Mlines^Mhere.^M

只有一行了,这根本不是我要的结果!
其中 “$” 表示换行符,”^M” 表示 <CR> 字符。由于是在 Linux 下面,所以只认 <LF>,不认 <CR>。

当处理来自其它系统的文本文件的时候,结果极有可能出乎意料。这个时候我们首先想到的就应该是换行符的问题,如果没想到,那只能要么怀疑自己的双眼,要么怀疑自己编程的能力了 :-)

要彻底摆脱文件格式的困扰,我们必须掌握这两个技能:

  1. 判断一个文本文件到底采用了哪种文件格式
  2. 知道它所采用的文件格式后,还要能够把它转换成想要的其它文件格式

值得庆幸的是,用 Vim 就能轻易地完成这两项任务。在 .vimrc 中添加下面这行:

set fileformats=unix,dos,mac

Vim 就会依次猜测文件是否采用了 unix, dos, mac 格式。为了能实时了解,可以在 Vim 的状态栏显示文件格式信息,只需在 .vimrc 中添加这行:

set statusline=%t%m%r%h%w[%L][%{&ff}][%{(&fenc==\"\")?&enc:&fenc}]%y[%p%%][%04l,%04v]

红色部分对应文件格式,其它部分的含义请在 Vim 中 :help 'statusline'

效果如下:

好了,现在我们只要用 Vim 打开一个文本文件,就能知道它的文件格式了。

用 Vim 来转换文件格式也非常简单,在命令模式下,输入 :set fileformat=dos(还可以是 unix/mac),然后 :w 写入文件,就完成转换了。

除了 Vim,在 UNIX/Linux/Mac 系统中还有两个工具可以用:dos2unix 和 unix2dos,它们的含义只要看名字就能明白了。

Tor, Polipo & Vidalia

xiaoyong Post in 技术,Tags: , , ,4,169 views
3

如果看到这个标题不能立刻联想到本篇文章的内容,那么你已经 Out 了。作为新时代女性“十得”之一,“翻墙术”必须加以普及。如果你和我一样,厌烦了“连接被重置”,那么标题中的 3 样利器就是一套流行的解决方案。

Tor 提供 SOCKS 代理,Polipo 通过 Tor 提供 HTTP 代理,Vidalia 则提供 Tor 的图形配置界面。这 3 样工具都是跨平台的,不管是在 Windows/Linux/Mac OS X 下都能使用。本文以 Linux 为例,较详细的介绍安装和配置方法。对于其它平台,安装过程不同,配置方法类似。

1. 安装

在 Fedora 下,用以下命令安装:

# yum install tor polipo vidalia

2. 给 bridges@torproject.org 发一封邮件,标题和内容均为 get bridges 。你会收到一封回信,内容是 3 个网桥的 IP 和端口,后面会用到。

3. 修改配置文件

对于 Tor 使用默认的即可;对于 Polipo,Tor 的官网上给出了一个示例文件,用那个即可。

$ wget https://svn.torproject.org/svn/torbrowser/trunk/build-scripts/config/polipo.conf # 下载配置文件
$ mv polipo.conf ~/.vidalia/polipo.conf # 放到合适的位置,如果没有这个目录就自己新建一个

4. 设置 Vidalia

启动 Vidalia -> 单击 Control Panel 上的 Settings 按钮 -> 在 General 标签下,设置 Proxy Application 为 Polipo,并填完整 Polipo 运行时的参数,就像这样:

-> 单击 Network 标签,选中 My ISP blocks connections to the Tor network,把前面得到的 3 个网桥都添加上去,就像这样:

-> 重启 Vidalia,第一次连接需要比较长的时间,耐心等待,当系统托盘上的洋葱头变成绿色的时候,就连接成功了。

5. 设置浏览器的 HTTP 代理为 127.0.0.1:8118,就能通过 Tor 来浏览网页了。如果你用 Firefox, 推荐安装 Torbutton 扩展。在 Torbutton 的配置界面里选择 Use Polipo 那项,就像这样:

在浏览器右下角状态栏右侧会有提示是否启用 Tor,可以通过单击来方便地切换启用/禁用 Tor。

参考:

1. https://www.torproject.org/docs/tor-doc-unix.html.en
2. http://bbs.fedora-zh.org/showthread.php?p=17494

FeedBurner 被封

xiaoyong Post in 技术,Tags: , ,1,030 views
0

一直以来我都用 FeedBurner 来管理本博客的 RSS 订阅,相比国内的 Feedsky,前者以其稳定而更新速度快深受我的喜爱。可是人生不如意,十之八九,更何况我们生活在傻X的围墙之内。这么优秀的工具,竟然被封了,而我却不觉得惊奇。

上有政策,下有对策,中国网民的电脑技术就在一次又一次被折腾的过程中得到提升。下面给出几种应对方法。

  1. 翻出墙外,重获自由。
  2. 如果你用 Google 阅读器,那么只需把 URL 中 http:// 改为 https://,即通过 https://reader.google.com/ 访问阅读器即可。
  3. 由于墙的疏忽,还有一种很 2 的方法,把本博客的 RSS 源改为 http://feeds2.feedburner.com/xiaoyong 就可以了。不过不敢保证这种方法何时会失效。

让 Vim 支持 CUDA 语法高亮

xiaoyong Post in 技术,Tags: , , ,2,586 views
4

最近在学 CUDA 编程,发现在服务器上用 Vim 写代码的时候,不能实现语法高亮,而在我的笔记本上则可以。查了一下,原来 Vim 自版本 7.2 之后才支持 CUDA 的语法。服务器上的 Vim 版本比较旧,所以不支持。

虽然默认不支持,我们还是有办法通过安装插件来让它支持的。Vim 的语法文件放在 /usr/share/vim/vim72/syntax/ (对于版本 7.2)下,把较新版本 Vim 的 CUDA 语法插件(/usr/share/vim/vim72/syntax/cuda.vim)拷贝到旧版本 Vim 的 ~/.vim/syntax/ 下,然后在 ~/.vimrc 中添加以下设置:

" CUDA syntax highlight {
    au BufNewFile,BufRead *.cu set ft=cuda
" }

最后看看效果如何:
在启用语法高亮之前,世界是黯淡的,

启用语法高亮之后,世界是多彩的。

向雷锋同志学习

xiaoyong Post in 生活,Tags: ,1,471 views
1

初中的时候,我在老师眼中是典型的“乖孩子”,仅仅因为我的成绩还不错。有一次,班主任家访,我恰好在卧室里看书,给他留下了极好的印象。回学校后,一次班会上,老师点名表扬了我,说到我家访问时发现我在看书,还和我姐姐讨论问题,让大家都向我学习。我被立为榜样了,同学们都投以羡慕的眼光。

故事讲到这里,似乎是我在显摆,但是请注意老师的话中看书一事是真,讨论问题一事是假的,是他为了让我显得更像榜样而随手添加的。有人欣赏自己不是令人愉快的事吗,多夸你一句又怎么了,何必斤斤计较呢?是的,这件事情本身没什么错,大家有了学习的榜样,而我则倍受鼓励,信心大增。但是这让我联想到了现实社会中比我伟大 n 倍的榜样、模范和英雄们。要树立像我这样一个微不足道的榜样尚且需要“添油加醋”,这让我不得不怀疑群众眼中的榜样、模范和英雄们事迹的真实性。

雷锋是个好同志,他的事迹广为流传,妇孺皆知。还有很多中学教科书上出现过的英雄们。他们或者为祖国抛头颅,洒热血,或者为建设祖国尽忠尽职,鞠躬尽瘁,或者为公共利益而牺牲自我利益。他们都是伟大的人,他们的事迹的确值得我们学习。不过榜样不是生而为榜样的,榜样也不是自封的。榜样的树立离不开第 3 方力量的推动,就像我能够成为同学们的榜样离不开老师的表扬一样。英雄很多时候是“被逼”的,是身不由己的。这样我们就不得不考量树立榜样者的用心。这用心可能是为了推动社会进步,国家发展,如英雄雷锋的树立;也可能罪大恶极,如日军侵华时进行“百人斩”杀人比赛,胜利者也被树立成为榜样。

人总是受着环境的影响,不过在接受别人的思想前不妨多一些 critical thinking ,可以减少犯错的几率。