<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>阮一峰的网络日志</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/" />
    <link rel="self" type="application/atom+xml" href="http://www.ruanyifeng.com/blog/atom.xml" />
    <id>tag:www.ruanyifeng.com,2010-04-11:/blog//1</id>
    <updated>2012-05-17T03:10:26Z</updated>
    <subtitle>Ruan YiFeng&apos;s Blog</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 5.13-en</generator>

<entry>
    <title>失败的总和----读《黄河青山：黄仁宇回忆录》</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/05/ray_huang_s_memoir.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1723</id>

    <published>2012-05-13T07:10:33Z</published>
    <updated>2012-05-17T03:10:26Z</updated>

    <summary>历史学家黄仁宇的最出名著作，大概非《万历十五年》莫属。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="Books" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>历史学家<a href="http://zh.wikipedia.org/wiki/%E9%BB%83%E4%BB%81%E5%AE%87">黄仁宇</a>的最出名著作，大概非<a href="http://zh.wikipedia.org/zh-cn/%E8%90%AC%E6%9B%86%E5%8D%81%E4%BA%94%E5%B9%B4">《万历十五年》</a>莫属。</p>]]>
        <![CDATA[<p><img src="http://image.beekka.com/blog/201205/bg2012051301.jpg" /></p>

<p>可是，我更喜欢他的回忆录<a href="http://lz.book.sohu.com/serialize-id-9481.html">《黄河青山》</a>。</p>

<p><img src="http://image.beekka.com/blog/201205/bg2012051303.jpg" /></p>

<p>多年前，在学校图书馆读到的时候，就觉得这本书很特别，讲述了一个国民党军官如何变成一个历史学家，夹叙夹议，将个人命运放在历史背景上，写得非常生动。</p>

<p>========================================================================</p>

<p>最近，我重读这本书，才发觉以前读得太粗糙，完全没有领会作者的用意。通常来说，自传总是记录一些令人骄傲的个人经历，可是打开《黄河青山》，你只看到一件接着一件的失败。</p>

<p>全书一开始，就是黄仁宇的恋爱失败：</p>

<blockquote>

<p>"1945年末，我遇见一个比自己小一岁的女孩，名字叫安，我对她一见倾心。许多天的下午及黄昏时刻，我从第三方面军总部借出吉普车，停在她家门口。佣人带我进到起居室，我就一直等，只听到走道中某处有座老式座钟发出的滴答声。安很少让我只等二十分钟。</p>

<p>即使我的虚荣心再强，都无法骗自己说，安曾经爱过我。......这样也好，因为如果她说,"让我们结婚吧，你最好认真一点"，我就会不知所措。我的新羊毛制服经过适当的熨烫后，勉强让我可以在上海的社交圈中走动。但除此以外，身为上尉的我，甚至负担不起一间套房。我的母亲、弟弟及妹妹仍然住在重庆的山间破屋中，甚至没有自来水可用，更不要说每一层都有浴室了。"</p>

</blockquote>

<p>然后，他开始讲自己选择人生道路的失败。1937年，他是南开大学电机系的二年级学生，听到日军入侵，不顾父亲的反对，毅然决定投笔从戎。</p>

<blockquote>

<p>"抗战爆发后不久，沿海各处相继失陷，我即立意去从军。"</p>

</blockquote>

<p>30年代，大学生当兵是一件极其稀有的事情。这种爱国热情当然值得肯定，可是从历史角度来看，他放弃工程师生涯，选择加入军队，等于选择了失败的人生。而且，毫不意外地，他不选择加入共产党。</p>

<blockquote>

<p>"1938年，我个人反对延安是因为他们教的是游击战，并不合我的胃口。我觉得如果要当职业军人，就应该领导军队进攻。我甚至想当拿破仑。躲在暗处放冷箭，然后快速逃走，听起来可不光彩，不是我要做的事。"</p>

</blockquote>

<p>讽刺的是，加入国民党军以后，他也没有上战场，而是被送到成都中央军校，大部分时间都在练习踢正步，等到三年后出来，抗日战争已经接近尾声。他作为军官被派到云南前线，可是日军临时放弃进攻云南，导致他连续几个月驻守在大山里，无所事事。这时，他开始体会到理想与现实的巨大差距。</p>

<blockquote>

<p>"我们还停留在明朝的条件。如果我需要一头驴来驮负重物，我必须派士兵到村落里去找村长，在枪支的威胁下，他可能听从我们的差遣。至于邮政，要送一封信到邻近的省份，必须耗上一个月的时间。我必须慎选词汇，才能让村民听懂我说的话。"</p>

</blockquote>

<blockquote>

<p>"士兵穿着冬季的棉袄蜷缩身体入睡，用蚊帐、毛毯或帆布当被子，抓到什么就盖什么，甚至几个人合盖一床被。地板上则铺着稻草，这样的环境造就了虱子的天堂。"</p>

</blockquote>

<blockquote>

<p>"我们的兵士每月薪饷十二元，身为上尉的我，月薪也不过四十元。可是，山头上的土匪开出每支枪七千元的条件，而且保障携枪逃亡者的安全。......有些连队晚上把步枪锁起来，军官睡觉时把手枪放在枕头下。"</p>

</blockquote>

<p>战争的最后阶段，黄仁宇的部队开赴缅甸，终于与日军正面作战了。可是，他在书中一笔带过那些"光辉经历"，比如，被日军狙击手击中大腿，差点丧命，或者给全国第一大报《大公报》当战地记者，后来出了一本《缅北之战》。详细写的，却是下面这样的事情：</p>

<blockquote>

<p>"一大块生铁从炮壳剥落，飞落到身旁不远处，我才知道自己逃过一劫。我本能想捡起来当纪念品，却发现铁片滚烫难耐，手掌几乎长水泡。"</p>

</blockquote>

<blockquote>

<p>"一天晚上，自部队后方传来'卡碰'声，前方部队于是向我们还击。一片混乱中，后方部队也朝我们射击，机关枪及迫击炮此起彼落。为了避免被击中，我们尽量压低身体，浸泡在湿寒冰冷中。"</p>

</blockquote>

<p>日军投降后，内战开始，他始终不受重用，最后还被怀疑可能叛变。调查表明他是清白的，但是他最终还是被强制退役。</p>

<blockquote>

<p>"我不知道台北当局如何处理我的退役。我请成都中央军校的同班同学汪奉曾上校回台北时，帮我查查我在国防部的档案。他说我的退役完全合乎规定，记录上还添了备注：'该军官应永远不再委任或聘用'。"</p>

</blockquote>

<p>既然成了平民，大陆和台湾都回不了，黄仁宇只好来到美国，以34岁的"高龄"重新进入大学读本科。</p>

<blockquote>

<p>"时年34岁还是大学生的我，除了学费偶尔可以延后缴纳外，得不到任何单位的帮助，长期的工读生涯就成为很自然的结果。有一次，唐纳德·季林教授问我几个中国内战的问题，我那时在当电梯服务员。我对他说，我不介意回答他的问题，但我必须工作，他可能要上上下下电梯好几次。"</p>

</blockquote>

<p>他有过各种各样的打工经历。</p>

<blockquote>

<p>"我经历过各种工作形态：全职工作、兼职工作、一周上两天班、只在周末和学校放假日上班、完全停掉工作、重新申请等等，大部分是在餐饮业。"</p>

</blockquote>

<blockquote>

<p>"在餐厅当打杂小弟，必须穿上浆过的白制服，戴上顶端有个网子的白帽。店内有儿童时，收银员会按铃，我就冲上前去帮他们处理杯盘。我第一次做这件事时，一位年轻的妈妈对儿子说：'把盘子留着，只要给那个中国人就行了。'小孩好像听不懂，她又说：'艾瑞克，我告诉你，只要给那个中国小弟就行了！'我当时已年近四十，待在学校的时间多过其他人。不过我也找不到抱怨的原因，谁叫我做的工作就是打杂'小弟'呢。"</p>

</blockquote>

<p>博士毕业后，依靠老师余英时的帮忙，他才在纽约州一所师范类大学找到了一个教职。可是，一所美国地方大学，会有多少学生对中国古代史的课程感兴趣呢？</p>

<blockquote>

<p>"只有6到10名学生选我的课，一半以上消失得无影无踪，或是不定期来上课，我根本无法准备教材，不知该针对谁的水准来上课。负责任的学生向我抱怨，宿舍太过吵闹喧嚣，再也无法念书（，所以来上课）。懒惰的学生持续扰乱我上课，有一名学生已经缺席两星期，竟然在课堂上要我简述前两堂课的内容。如果不回答这种扰乱秩序的问题，只会弘扬我心胸偏狭的名声。"</p>

</blockquote>

<blockquote>

<p>"我已经养成习惯，只要学生连续缺席几次，我就设法联络他们。我的学生一开始就很少，可不能再丢掉任何一个。"</p>

</blockquote>

<p>更糟糕的是，1979年，校方通知黄仁宇，他被解聘了。那时，他已经61岁了。</p>

<blockquote>

<p>"当天晚上，妻子将消息告知我们的儿子。当时他只有11岁，还在念中学。在这个很小的大学城，人人都知道别人的举动及遭遇。直到今天，只要想到1979年3月27日那一天，我的儿子如何接受这个令人不快的消息，我就觉得很难过。儿子知道他的父亲已被解聘，而许多同学的父母却在大学里有杰出表现。有人的妈妈最近被选为系主任，有人的父亲筹组野外探险队，带学生去特殊景点，但他的父亲却被解聘了。他仍然坚持要我去参观他的赛跑大会和学校音乐会，但在心里一定也和父母一样难过。有些同学好奇地问他，你爸爸下一步要怎么办？我接到通知的数天后，邻家十岁男童丹尼走近在后院的我：'你要卖房子吗?'"</p>

</blockquote>

<p>解聘以后，找不到工作。</p>

<blockquote>

<p>"我没有办法再找到另一个职位，即使朋友们试着帮我忙，但没有人会雇用一个刚被解聘的六十多岁的人。"</p>

</blockquote>

<p>生活水准急剧下降。</p>

<blockquote>

<p>"我被解聘后，就没有找到工作，也没有申请到研究经费。目前，我的家庭支出大半依靠社会福利津贴，每个月500美元，我的妻子和儿子也可以各领450美元。此外，我每个月的教师年金300美元。这些钱让我们勉强维生，略微超过最低生活水平。我的版税收入可以用来缴税，有时还要动用我妻子的储蓄。我只要一听到热水器要更新，或是屋顶有破洞，心都会一阵抽痛。我们可以设法偶尔附近玩玩，但如果要去一次纽约，家庭预算就必须重新大幅更动。我每次定大笔出版品或买几本书时，就必须考虑财源。"</p>

</blockquote>

<p>直到《万历十五年》出版，在中国引起轰动，黄仁宇的经济状况才开始逐步改善。自传也就写到这个地方。</p>

<p>==================================================================</p>

<p><strong>看了上面摘录，我们不禁要问，为什么黄仁宇只强调自己的人生失败，他想证明什么？</strong>大多数自传都在自我美化，你何时见过，有人执意要把自己塑造为"失败者"（Loser），还写成500页的传记，一定要让后人记住这一点？</p>

<p>我联想到了《万历十五年》，里面一共写了六个人物----万历皇帝、申时行、张居正、海瑞、戚继光、李贽----他们也全部失败了。事实上，《万历十五年》的主题就是，中国作为一个整体的失败。它的结尾是这样的：</p>

<blockquote>

<p>"当一个人口众多的国家，个人行动全凭儒家简单粗浅而又无法固定的原则所限制，而法律又缺乏创造性，则其社会发展的程度，必然受到限制。即便是宗旨善良，也不能补助技术之不及。1587年，是为万历十五年，丁亥次岁，表面上似乎是四海升平，无事可记，实际上我们的大明帝国却已经走到了它发展的尽头。在这个时候，皇帝的励精图治或者宴安耽乐，首辅的独裁或者调和，高级将领的富于创造或者习于苟安，文官的廉洁奉公或者贪污舞弊，思想家的极端进步或者绝对保守，最后的结果，都是无分善恶，统统不能在事业上取得有意义的发展，有的身败，有的名裂，还有的人则身败而兼名裂。</p>

<p>因此我们的故事只好在这里作悲剧性的结束。万历丁亥年的年鉴，是为历史上一部失败的总记录。"</p>

</blockquote>

<p>仔细阅读这段话，<strong>"最后的结果，都是无分善恶，统统不能在事业上取得有意义的发展"</strong>，这就是说，失败是不可避免的。《万历十五年》的主题是，中国的失败不可避免；那么《黄河青山》的意思是不是说，黄仁宇个人的失败不可避免？两者之间有什么联系吗？</p>

<blockquote>

<p>"我写回忆录不是为了自己，而是为了说明我的背景，为了特定的历史史观。"</p>

</blockquote>

<p>显然，黄仁宇在用自传，解释他的历史观。</p>

<blockquote>

<p>"在美国读书和打工时，我常被在中国的痛苦回忆所折磨，不时陷入沉思。后来当教师，拿着麦克风站在五百名大学生面前，无法立即解释：为何康有为失败了，孙中山失败了，袁世凯失败了，张作霖失败了，陈独秀失败了，蒋介石失败了，而毛泽东也失败了。为使我的讲课内容前后一致又有说服力，唯一的方法就是说，中国的问题大于上述人士努力的总和。中国文明将和西方文明融合的说法，是人类历史上空前的事件。上述不同阶段的失败必须被视为阶段的调试，以达成一致的终点。对我们这些有后见之识的人来说，这点很明显，但舞台上的演员看不到。"</p>

</blockquote>

<p>这是黄仁宇在解释为什么他要写《万历十五年》，<strong>"中国的问题大于上述人士努力的总和。上述不同阶段的失败必须被视为阶段的调试，以达成一致的终点。"</strong>那么，推广到黄仁宇自己身上，是不是他在暗示，自己的各种失败大于努力的总和，而这些失败必须被视为对历史的阶段性调试，最终将到达一个更深远的终点？</p>

<blockquote>

<p>"我开始领悟，为何我必须在生命中见识如此多的奇人异事，面临如此多的暴力。我恰巧出生在中国政治的最低点，以及人心惶惶的最高点。</p>

<p>我阅读的东西，听过的对话，在中国见证的事件，都只有在我迁居美国多年后才产生意义。由于离主体很远，又有够长的时间来发展后见之明，终于可以轮到我说，我懂了。"</p>

</blockquote>

<p>黄仁宇是在说，他的个人失败，是20世纪中国遭受挫折的一种个体反映。</p>

<blockquote>

<p>"以长期观点阅读中国现代历史时，就不会连连沮丧，反而会看到全本的戏剧在眼前开展。中国历史很可能即将融入世界历史，不但是空前的进展，而且是实质上的融和，不再缺乏希望与期许，纵使还会有挫败及暂时的逆转。"</p>

</blockquote>

<p>如果你看到了历史的长期合理性，那么当你经历了种种失败，年老时回望自己人生，才能平静地接受命运，体会其中的必然，然后静静地等待隧道的尽头开始展现一丝曙光，证明那些企图逆转命运的举动，并非无谓和徒劳，一切自有内在的因果。这大概就是《黄河青山》的写作目的吧。</p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/05/ray_huang_s_memoir.html">http://www.ruanyifeng.com/blog/2012/05/ray_huang_s_memoir.html</a></li>
<li>最后修改时间：2012年5月17日 11:10</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>自适应网页设计（Responsive Web Design）</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/05/responsive_web_design.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1722</id>

    <published>2012-05-01T06:57:01Z</published>
    <updated>2012-05-16T18:26:19Z</updated>

    <summary>随着3G的普及，越来越多的人使用手机上网。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="CSS" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>随着3G的普及，越来越多的人使用手机上网。</p>]]>
        <![CDATA[<p>移动设备正超过桌面设备，成为访问互联网的最常见终端。于是，网页设计师不得不面对一个难题：如何才能在不同大小的设备上呈现同样的网页？</p>

<p><img src="http://image.beekka.com/blog/201205/bg2012050101.jpg" /></p>

<p>手机的屏幕比较小，宽度通常在600像素以下；PC的屏幕宽度，一般都在1000像素以上（目前主流宽度是1366×768），有的还达到了2000像素。同样的内容，要在大小迥异的屏幕上，都呈现出满意的效果，并不是一件容易的事。</p>

<p>很多网站的解决方法，是为不同的设备提供不同的网页，比如专门提供一个mobile版本，或者iPhone / iPad版本。这样做固然保证了效果，但是比较麻烦，同时要维护好几个版本，而且如果一个网站有多个portal（入口），会大大增加架构设计的复杂度。</p>

<p>于是，很早就有人设想，能不能"一次设计，普遍适用"，让同一张网页自动适应不同大小的屏幕，根据屏幕宽度，自动调整布局（layout）？</p>

<p><img src="http://image.beekka.com/blog/201205/bg2012050107.jpg" /></p>

<p><strong>一、"自适应网页设计"的概念</strong></p>

<p>2010年，Ethan Marcotte提出了<a href="http://www.alistapart.com/articles/responsive-web-design/">"自适应网页设计"</a>（Responsive Web Design）这个名词，指可以自动识别屏幕宽度、并做出相应调整的网页设计。</p>

<p>他制作了一个<a href="http://www.alistapart.com/d/responsive-web-design/ex/ex-site-flexible.html">范例</a>，里面是《福尔摩斯历险记》六个主人公的头像。如果屏幕宽度大于1300像素，则6张图片并排在一行。</p>

<p><img src="http://image.beekka.com/blog/201205/bg2012050103.jpg" /></p>

<p>如果屏幕宽度在600像素到1300像素之间，则6张图片分成两行。</p>

<p><img src="http://image.beekka.com/blog/201205/bg2012050104.jpg" /></p>

<p>如果屏幕宽度在400像素到600像素之间，则导航栏移到网页头部。</p>

<p><img src="http://image.beekka.com/blog/201205/bg2012050105.jpg" /></p>

<p>如果屏幕宽度在400像素以下，则6张图片分成三行。</p>

<p><img src="http://image.beekka.com/blog/201205/bg2012050106.jpg" /></p>

<p><a href="http://mediaqueri.es/">mediaqueri.es</a>上面有更多这样的例子。</p>

<p>这里还有一个<a href="http://www.benjaminkeen.com/misc/bricss/">测试小工具</a>，可以在一张网页上，同时显示不同分辨率屏幕的测试效果，我推荐安装。</p>

<p><strong>二、允许网页宽度自动调整</strong></p>

<p>"自适应网页设计"到底是怎么做到的？其实并不难。</p>

<p>首先，在网页代码的头部，加入一行<a href="https://developer.mozilla.org/en/mobile/viewport_meta_tag">viewport元标签</a>。</p>

<blockquote>

<p>　　&lt;meta name="viewport" content="width=device-width, initial-scale=1" /&gt;</p>

</blockquote>

<p><a href="https://developer.apple.com/library/ios/#DOCUMENTATION/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html">viewport</a>是网页默认的宽度和高度，上面这行代码的意思是，网页宽度默认等于屏幕宽度（width=device-width），原始缩放比例（initial-scale=1）为1.0，即网页初始大小占屏幕面积的100%。</p>

<p>所有主流浏览器都支持这个设置，包括IE9。对于那些老式浏览器（主要是IE6、7、8），需要使用<a href="http://code.google.com/p/css3-mediaqueries-js/">css3-mediaqueries.js</a>。</p>

<blockquote>

<p>　　&lt;!--[if lt IE 9]&gt;<br />
　　　　&lt;script src="http://css3-mediaqueries-js.googlecode.com/svn/trunk/css3-mediaqueries.js"&gt;&lt;/script&gt;<br />
　　&lt;![endif]--&gt;</p>

</blockquote>

<p><strong>三、不使用绝对宽度</strong></p>

<p>由于网页会根据屏幕宽度调整布局，所以不能使用绝对宽度的布局，也不能使用具有绝对宽度的元素。这一条非常重要。</p>

<p>具体说，CSS代码不能指定像素宽度：</p>

<blockquote>

<p>　　width:xxx px;</p>

</blockquote>

<p>只能指定百分比宽度：</p>

<blockquote>

<p>　　width: xx%;</p>

</blockquote>

<p>或者</p>

<blockquote>

<p>　　width:auto;</p>

</blockquote>

<p><strong>四、相对大小的字体</strong></p>

<p>字体也不能使用绝对大小（px），而只能使用相对大小（em）。</p>

<blockquote>

<p>　　body {<br />
　　　　font: normal 100% Helvetica, Arial, sans-serif;<br />
　　}</p>

</blockquote>

<p>上面的代码指定，字体大小是页面默认大小的100%，即16像素。</p>

<blockquote>

<p>　　h1 {<br />
　　　　font-size: 1.5em; <br />
　　}</p>

</blockquote>

<p>然后，h1的大小是默认大小的1.5倍，即24像素（24/16=1.5）。</p>

<blockquote>

<p>　　small {<br />
　　　　font-size: 0.875em;<br />
　　}</p>

</blockquote>

<p>small元素的大小是默认大小的0.875倍，即14像素（14/16=0.875）。</p>

<p><strong>五、流动布局（fluid grid）</strong></p>

<p><a href="http://www.alistapart.com/articles/fluidgrids/">"流动布局"</a>的含义是，各个区块的位置都是浮动的，不是固定不变的。</p>

<blockquote>

<p>　　.main {<br />
　　　　float: right;<br />
　　　　width: 70%; <br />
　　}</p>

<p>　　.leftBar {<br />
　　　　float: left;<br />
　　　　width: 25%;<br />
　　}</p>

</blockquote>

<p><a href="http://designshack.net/articles/css/everything-you-never-knew-about-css-floats/">float</a>的好处是，如果宽度太小，放不下两个元素，后面的元素会自动滚动到前面元素的下方，不会在水平方向overflow（溢出），避免了水平滚动条的出现。</p>

<p>另外，绝对定位（position: absolute）的使用，也要非常小心。</p>

<p><strong>六、选择加载CSS</strong></p>

<p>"自适应网页设计"的核心，就是CSS3引入的<a href="http://www.w3.org/TR/CSS21/media.html">Media Query</a>模块。</p>

<p>它的意思就是，自动探测屏幕宽度，然后加载相应的CSS文件。</p>

<blockquote>

<p>　　&lt;link rel="stylesheet" type="text/css"<br />
　　　　media="screen and (max-device-width: 400px)"<br />
　　　　href="tinyScreen.css" /&gt;</p>

</blockquote>

<p>上面的代码意思是，如果屏幕宽度小于400像素（max-device-width: 400px），就加载tinyScreen.css文件。</p>

<blockquote>

<p>　　&lt;link rel="stylesheet" type="text/css"<br />
　　　　media="screen and (min-width: 400px) and (max-device-width: 600px)"<br />
　　　　href="smallScreen.css" /&gt;</p>

</blockquote>

<p>如果屏幕宽度在400像素到600像素之间，则加载smallScreen.css文件。</p>

<p>除了用html标签加载CSS文件，还可以在现有CSS文件中加载。</p>

<blockquote>

<p>　　@import url("tinyScreen.css") screen and (max-device-width: 400px);</p>

</blockquote>

<p><strong>七、CSS的@media规则</strong></p>

<p>同一个CSS文件中，也可以根据不同的屏幕分辨率，选择应用不同的CSS规则。</p>

<blockquote>

<p>　　@media screen and (max-device-width: 400px) {</p>

<p>　　　　.column {<br />
　　　　　　float: none;<br />
　　　　　　width:auto;<br />
　　　　}</p>

<p>　　　　#sidebar {<br />
　　　　　　display:none;<br />
　　　　}</p>

<p>　　}</p>

</blockquote>

<p>上面的代码意思是，如果屏幕宽度小于400像素，则column块取消浮动（float:none）、宽度自动调节（width:auto），sidebar块不显示（display:none）。</p>

<p><strong>八、图片的自适应（fluid image）</strong></p>

<p>除了布局和文本，"自适应网页设计"还必须实现图片的<a href="http://unstoppablerobotninja.com/entry/fluid-images">自动缩放</a>。</p>

<p>这只要一行CSS代码：</p>

<blockquote>

<p>　　img { max-width: 100%;}</p>

</blockquote>

<p>这行代码对于大多数嵌入网页的视频也有效，所以可以写成：</p>

<blockquote>

<p>　　img, object { max-width: 100%;}</p>

</blockquote>

<p>老版本的IE不支持max-width，所以只好写成：</p>

<blockquote>

<p>　　img {  width: 100%; }</p>

</blockquote>

<p>此外，windows平台缩放图片时，可能出现图像失真现象。这时，可以尝试使用IE的<a href="http://css-tricks.com/ie-fix-bicubic-scaling-for-images/">专有命令</a>：</p>

<blockquote>

<p>　　img { -ms-interpolation-mode: bicubic; }</p>

</blockquote>

<p>或者，Ethan Marcotte的<a href="http://unstoppablerobotninja.com/demos/resize/imgSizer.js">imgSizer.js</a>。</p>

<blockquote>

<p>　　addLoadEvent(function() {</p>

<p> 　　　　var imgs = document.getElementById("content").getElementsByTagName("img");</p>

<p>　　　　imgSizer.collate(imgs);</p>

<p>　　});</p>

</blockquote>

<p>不过，有条件的话，最好还是根据不同大小的屏幕，加载不同分辨率的图片。有<a href="http://blog.cloudfour.com/responsive-imgs-part-2/">很多方法</a>可以做到这一条，服务器端和客户端都可以实现。</p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/05/responsive_web_design.html">http://www.ruanyifeng.com/blog/2012/05/responsive_web_design.html</a></li>
<li>最后修改时间：2012年5月17日 02:26</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>Javascript编程风格</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/04/javascript_programming_style.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1721</id>

    <published>2012-04-27T10:30:18Z</published>
    <updated>2012-05-15T09:14:13Z</updated>

    <summary>Douglas Crockford是Javascript权威，Json格式就是他的发明。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="IT" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p><a href="http://www.crockford.com/">Douglas Crockford</a>是Javascript权威，<a href="http://www.ruanyifeng.com/blog/2009/05/data_types_and_json.html">Json格式</a>就是他的发明。</p>]]>
        <![CDATA[<p>去年11月他有一个演讲（<a href="http://www.youtube.com/watch?v=taaEzHI9xyY">Youtube</a>），谈到了好的Javascript编程风格是什么。</p>

<p><a href="http://www.youtube.com/watch?v=taaEzHI9xyY"><img src="http://image.beekka.com/blog/201204/bg2012042701.jpg" /></a></p>

<p>我非常推荐这个演讲，它不仅有助于学习Javascript，而且能让你心情舒畅，因为Crockford讲得很幽默，时不时让听众会心一笑。</p>

<p>下面，我根据这个演讲和Crockford编写的<a href="http://javascript.crockford.com/code.html">代码规范</a>，总结一下"Javascript编程风格"。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012042702.jpg" /></p>

<p><strong>所谓"编程风格"（programming style），指的是编写代码的样式规则。</strong>不同的程序员，往往有不同的编程风格。</p>

<p>有人说，编译器的规范叫做"语法规则"（grammar），这是程序员必须遵守的；而编译器忽略的部分，就叫"编程风格"（programming style），这是程序员可以自由选择的。这种说法不完全正确，<strong>程序员固然可以自由选择编程风格，但是好的编程风格有助于写出质量更高、错误更少、更易于维护的程序。</strong></p>

<p>所以，有一点应该明确，<strong>"编程风格"的选择不应该基于个人爱好、熟悉程度、打字工作量等因素，而要考虑如何尽量使代码清晰易读、减少出错。你选择的，不是你喜欢的风格，而是一种能够清晰表达你的意图的风格。</strong>这一点，对于Javascript这种语法自由度很高、设计<a href="http://www.ruanyifeng.com/blog/2010/01/12_javascript_syntax_structures_you_should_not_use.html">不完全成熟</a>的语言尤其重要。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012042704.jpg" /></p>

<p><strong>一、大括号的位置</strong></p>

<p>绝大多数的编程语言，都用大括号（{}）表示区块（block）。起首的大括号的位置，有许多不同的<a href="http://en.wikipedia.org/wiki/Indent_style">写法</a>。</p>

<p>最流行的有两种。一种是起首的大括号另起一行：</p>

<blockquote>

<p>　　block</p>

<p>　　{</p>

<p>　　　　...</p>

<p>　　}</p>

</blockquote>

<p>另一种是起首的大括号跟在关键字的后面：</p>

<blockquote>

<p>　　block {</p>

<p>　　　　...</p>

<p>　　}</p>

</blockquote>

<p>一般来说，这两种写法都可以接受。但是，Javascript要使用后一种，因为Javascript会自动添加句末的分号，导致一些难以察觉的错误。</p>

<blockquote>

<p>　　return </p>

<p>　　{</p>

<p>　　　　key:value;</p>

<p>　　};</p>

</blockquote>

<p>上面的代码的原意，是要返回一个对象，但实际上返回的是undefined，因为Javascript自动在return语句后面添加了分号。为了避免这一类错误，需要写成下面这样：</p>

<blockquote>

<p>　　return {</p>

<p>　　　　key : value;</p>

<p>　　};</p>

</blockquote>

<p>因此，</p>

<blockquote>

<p>　　<strong>规则1：表示区块起首的大括号，不要另起一行。</strong></p>

</blockquote>

<p><strong>二、 圆括号</strong></p>

<p>圆括号（parentheses）在Javascript中有两种作用，一种表示调用函数，另一种表示不同的值的组合（grouping）。我们可以用空格，区分这两种不同的括号。</p>

<blockquote>

<p>　　<strong>规则2：调用函数的时候，函数名与左括号之间没有空格。</strong></p>

</blockquote>

<blockquote>

<p>　　<strong>规则3：函数名与参数序列之间，没有空格。</strong></p>

</blockquote>

<blockquote>

<p>　　<strong>规则4：所有其他语法元素与左括号之间，都有一个空格。</strong></p>

</blockquote>

<p>按照上面的规则，下面的写法都是不规范的：</p>

<blockquote>

<p>　　foo (bar)</p>

<p>　　return(a+b);</p>

<p>　　if(a === 0) {...}</p>

<p>　　function foo (b) {...}</p>

<p>　　function(x) {...}</p>

</blockquote>

<p><img src="http://image.beekka.com/blog/201204/bg2012042705.jpg" /></p>

<p><strong>三、分号</strong></p>

<p>分号表示语句的结束。大多数情况下，如果你省略了句尾的分号，Javascript会自动添加。</p>

<blockquote>

<p>　　var a = 1</p>

</blockquote>

<p>等同于</p>

<blockquote>

<p>　　var a = 1;</p>

</blockquote>

<p>因此，有人<a href="http://mislav.uniqpath.com/2010/05/semicolons/">提倡</a>省略句尾的分号。但麻烦的是，如果下一行的第一个字元（token）是下面这五个字符之一，Javascript将不对上一行句尾<a href="http://inimino.org/~inimino/blog/javascript_semicolons">添加分号</a>："("、"["、"/"、"+"和"-"。</p>

<blockquote>

<p>　　x = y</p>

<p>　　(function (){</p>

<p>　　　　...</p>

<p>　　})();</p>

</blockquote>

<p>上面的代码等同于</p>

<blockquote>

<p>　　x = y(function (){...})();</p>

</blockquote>

<p>因此，</p>

<blockquote>

<p>　　<strong>规则5：不要省略句末的分号。</strong></p>

</blockquote>

<p><strong>四、with语句</strong></p>

<p>with可以减少代码的书写，但是会造成混淆。</p>

<blockquote>

<p>　　with (o) {</p>

<p>　　　　foo = bar;</p>

<p>　　}</p>

</blockquote>

<p>上面的代码，可以有四种运行结果：</p>

<blockquote>

<p>　　o.foo = bar;</p>

<p>　　o.foo = o.bar;</p>

<p>　　foo = bar;</p>

<p>　　foo = o.bar;</p>

</blockquote>

<p>这四种结果都可能发生，取决于不同的变量是否有定义。因此，</p>

<blockquote>

<p>　　<strong>规则6：不要使用with语句。</strong></p>

</blockquote>

<p><img src="http://image.beekka.com/blog/201204/bg2012042706.jpg" /></p>

<p><strong>五、相等和严格相等</strong></p>

<p>Javascript有两个表示"相等"的运算符："相等"（==）和"严格相等"（===）。</p>

<p>因为"相等"运算符会自动转换变量类型，造成很多意想不到的<a href="http://www.2ality.com/2011/06/javascript-equality.html">情况</a>：</p>

<blockquote>

<p>　　0 == ''// true</p>

<p>　　1 == true // true</p>

<p>　　2 == true // false</p>

<p>　　0 == '0' // true</p>

<p>　　false == 'false' // false</p>

<p>　　false == '0' // true</p>

<p>　　" \t\r\n " == 0 // true</p>

</blockquote>

<p>因此，</p>

<blockquote>

<p>　　<strong>规则7：不要使用"相等"（==）运算符，只使用"严格相等"（===）运算符。</strong></p>

</blockquote>

<p><strong>六、语句的合并</strong></p>

<p>有些程序员追求简洁，喜欢合并不同目的的语句。比如，原来的语句是</p>

<blockquote>

<p>　　a = b;</p>

<p>　　if (a) {...}</p>

</blockquote>

<p>他喜欢写成下面这样:</p>

<blockquote>

<p>　　if (a = b) {...}</p>

</blockquote>

<p>虽然语句少了一行，但是可读性大打折扣，而且会造成误读，让别人误以为这行代码的意思是：</p>

<blockquote>

<p>　　if （a === b）{...}</p>

</blockquote>

<p>另外一种情况是，有些程序员喜欢在同一行中赋值多个变量：</p>

<blockquote>

<p>　　var a = b = 0;</p>

</blockquote>

<p>他以为，这行代码等同于</p>

<blockquote>

<p>　　var a = 0, b = 0;</p>

</blockquote>

<p>实际上不是，它的真正效果是下面这样：</p>

<blockquote>

<p>　　b = 0;<br />
 <br />
　　var a = b;</p>

</blockquote>

<p>因此，</p>

<blockquote>

<p>　　<strong>规则8：不要将不同目的的语句，合并成一行。</strong></p>

</blockquote>

<p><img src="http://image.beekka.com/blog/201204/bg2012042707.jpg" /></p>

<p><strong>七、变量声明</strong></p>

<p>Javascript会自动将变量声明"提升"（hoist）到代码块（block）的头部。</p>

<blockquote>

<p>　　if (!o) {</p>

<p>　　　　var o = {};</p>

<p>　　}</p>

</blockquote>

<p>等同于</p>

<blockquote>

<p>　　var o;</p>

<p>　　if (!o) {</p>

<p>　　　　o = {};</p>

<p>　　}</p>

</blockquote>

<p>为了避免可能出现的问题，不如把变量声明都放在代码块的头部。</p>

<blockquote>

<p>　　for (var i ...) {...}</p>

</blockquote>

<p>最好写成：</p>

<blockquote>

<p>　　var i;<br />
 <br />
　　for (i ...) {...,}</p>

</blockquote>

<p>因此，</p>

<blockquote>

<p>　　<strong>规则9：所有变量声明都放在函数的头部。</strong></p>

</blockquote>

<blockquote>

<p>　　<strong>规则10：所有函数都在使用之前定义。</strong></p>

</blockquote>

<p><strong>八、全局变量</strong></p>

<p>Javascript最大的语法缺点，可能就是全局变量对于任何一个代码块，都是可读可写。这对代码的模块化和重复使用，非常不利。</p>

<blockquote>

<p>　　<strong>规则11：避免使用全局变量；如果不得不使用，用大写字母表示变量名，比如UPPER_CASE。</strong></p>

</blockquote>

<p><img src="http://image.beekka.com/blog/201204/bg2012042708.jpg" /></p>

<p><strong>九、new命令</strong></p>

<p>Javascript使用new命令，从建构函数生成一个新对象。</p>

<blockquote>

<p>　　var o = new myObject();</p>

</blockquote>

<p>这种做法的问题是，一旦你忘了加上new，myObject()内部的this关键字就会指向全局对象，导致所有绑定在this上面的变量，都变成全部变量。</p>

<blockquote>

<p>　　<strong>规则12：不要使用new命令，改用<a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create">Object.create()</a>命令。</strong></p>

</blockquote>

<p>如果不得不使用new，为了防止出错，最好在视觉上把建构函数与其他函数区分开来。</p>

<blockquote>

<p>　　<strong>规则13：建构函数的函数名，采用首字母大写（InitialCap）；其他函数名，一律首字母小写。</strong></p>

</blockquote>

<p><strong>十、自增和自减运算符</strong></p>

<p>自增（++）和自减（--）运算符，放在变量的前面或后面，返回的值不一样，很容易发生错误。</p>

<p>事实上，所有的++运算符都可以用"+= 1"代替。</p>

<blockquote>

<p>　　++x</p>

</blockquote>

<p>等同于</p>

<blockquote>

<p>　　x += 1;</p>

</blockquote>

<p>代码变得更清晰了。有一个很可笑的例子，某个Javascript函数库的源代码中出现了下面的片段：</p>

<blockquote>

<p>　　++x;</p>

<p>　　++x;</p>

</blockquote>

<p>这个程序员忘了，还有更简单、更合理的写法：</p>

<blockquote>

<p>　　x += 2;</p>

</blockquote>

<p>因此，</p>

<blockquote>

<p>　　<strong>规则14：不要使用自增（++）和自减（--）运算符，用+=和-=代替。</strong></p>

</blockquote>

<p><strong>十一、区块</strong></p>

<p>如果循环和判断的代码体只有一行，Javascript允许该区块（block）省略大括号。</p>

<p>下面的代码</p>

<blockquote>

<p>　　if (a) b(); c();</p>

</blockquote>

<p>原意可能是</p>

<blockquote>

<p>　　if (a) { b(); c();}</p>

</blockquote>

<p>但是，实际效果是</p>

<blockquote>

<p>　　if (a) { b();} c();</p>

</blockquote>

<p>因此，</p>

<blockquote>

<p>　　<strong>规则15：总是使用大括号表示区块。</strong></p>

</blockquote>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/04/javascript_programming_style.html">http://www.ruanyifeng.com/blog/2012/04/javascript_programming_style.html</a></li>
<li>最后修改时间：2012年5月15日 17:14</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>居延汉简和安阳殷墟1001号大墓</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/04/museum_of_institute_of_history_and_philology.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1720</id>

    <published>2012-04-19T17:38:01Z</published>
    <updated>2012-05-13T06:11:59Z</updated>

    <summary>中央研究院是台湾的最高学术研究机构，里面有很多研究所。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="History" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p><a href="http://zh.wikipedia.org/zh/%E4%B8%AD%E5%A4%AE%E7%A0%94%E7%A9%B6%E9%99%A2">中央研究院</a>是台湾的最高学术研究机构，里面有很多研究所。</p>]]>
        <![CDATA[<p>此外，还有不少<a href="http://www.sinica.edu.tw/museum.htm">展览馆</a>，可以免费参观。<a href="http://www.ihp.sinica.edu.tw">历史语言研究所</a>的历史文物陈列馆，就令我大开眼界。</p>

<p>1.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041801.jpg" /></p>

<p>"<a href="http://www.ruanyifeng.com/blog/2012/04/hu_shih.html">胡适纪念馆</a>"的不远处，就是历史语言研究所大楼。底下两层是该所收藏文物的<a href="http://www.asihp.net/~museum/">陈列馆</a>。</p>

<p>2.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041802.jpg" /></p>

<p>陈列室的前厅，简洁而富有现代感。外人很难想象，这里收藏着代表着中国考古最高成就的文物。</p>

<p>3.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041803.jpg" /></p>

<p>走进二楼的入口，迎面就是"居延汉简"的展室，令我惊喜异常。</p>

<p>4.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041804.jpg" /></p>

<p>以前只在书上看过，1930年，中国和瑞典历史学家组成的"西北科学考察团"，来到甘肃、内蒙交界处的荒漠，考察汉代边塞遗址"居延"。2000多年前，大汉王朝在那里每隔几里，就修建一个"烽燧"，一旦发现匈奴入侵，里面的士兵立刻点起狼烟报警。后来，这些烽燧都成了荒丘。（上图为红城遗址，位于内蒙古额济纳旗，是居延地区保存最完好的汉代建筑遗址之一，照片取自互联网。）</p>

<p>5.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041805.jpg" /></p>

<p>1930年4月底，考察队的瑞典历史学家弗克•贝格曼（Folke Bergman）进入了一座汉代城堡，他<a href="http://news.guoxue.com/article.php?articleid=14267">发现</a>"城堡东侧是宿舍和厨房，还有一间不足6平方米的小屋，里面有成册的木简，其中一份是汉元帝永光二年（公元前42年）一个下级武官丧父的报告书，另一份为汉和帝永元五年（公元93年）的账簿。专家们推测这里可能是当时的档案室，后来的发掘证实了这一推断。"（图为汉代要塞的复原图。）</p>

<p>6.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041806.jpg" /></p>

<p>考古学家们大喜过望，将考察重点转向发掘这些汉代书简，结果一共挖到了1万多枚，统称为"居延汉简"。它们大大加深了我们对汉朝的了解，国学大师王国维兴奋地将其与安阳甲骨文、敦煌藏经洞、紫禁城大内档案，一起并称为"20世纪中国文化界四大发现之一"。（图为出土时的居延汉简。）</p>

<p>7.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041807.jpg" /></p>

<p>1949年，这批宝贵文物被运到了台湾，从此我们只能在书上读到。今天，我能亲眼目睹，怎不激动。眼前的中央展柜，存放的就是这批汉简中最长的一份----77根汉简组成一张武器清单，上面记载着要塞中釜、弩、箭等兵器的清点结果。</p>

<p>8.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041808.jpg" /></p>

<p>看一下细节。</p>

<p>9.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041809.jpg" /></p>

<p>这个就是当年弗克•贝格曼发现的第一份木简。公元前42年，一个姓郑的军官，因为父亲去世，要求请假回内地奔丧。这份木简完全保持原样，连上面的绳子都是汉朝留下来的。</p>

<p>10.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041810.jpg" /></p>

<p>"居延汉简"的内容，大部分与军事有关，比如记载匈奴的动向。</p>

<p>11.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041811.jpg" /></p>

<p>也有不少反映政治的内容，比如皇帝的诏书和各种敕令。以及反映日常生活的内容，上图就是随军家属的领粮记录。</p>

<p>12.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041812.jpg" /></p>

<p>除了汉简之外，还挖掘出了一大批其他文物，使得我们仿佛看到了活生生的汉代戍边士兵的生活。上图为画着人脸的木片，大概是士兵用来避邪的。</p>

<p>13.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041813.jpg" /></p>

<p>这个楔形的木器，初看不知道是什么东西。</p>

<p>14.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041814.jpg" /></p>

<p>红外线下，才发现上面写有文字。原来，它是用来封囊袋的，袋子的口就穿过木器上方的孔，上面的文字则是记录了袋子里面的东西，大多数是衣服。</p>

<p>15.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041815.jpg" /></p>

<p>士兵用的木杯子。</p>

<p>16.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041816.jpg" /></p>

<p>汉代的梳子。</p>

<p>17.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041817.jpg" /></p>

<p>汉代的毛笔，木简就是用这种笔写的。</p>

<p>18.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041818.jpg" /></p>

<p>用来射匈奴的箭杆。</p>

<p>19.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041819.jpg" /></p>

<p>士兵吃的谷子。这是考古学家一粒粒捡起来的，放在随身的火柴盒里。</p>

<p>20.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041820.jpg" /></p>

<p>所有这些文物，都是2000年前的东西。当我与它们面对面的时候，觉得汉朝也不是那么遥远，甚至触手可及。范仲淹笔下的西域大漠，"长烟落日孤城闭，羌管悠悠霜满地"，仿佛在眼前浮现，而戍边士兵的心境"浊酒一杯家万里，燕然未勒归无计"，仿佛与今人是如此相通。（上图为考古学家整理和辨识汉简的笔记。）</p>

<p>21.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041821.jpg" /></p>

<p>二楼的其他文物，这里就从略了。不过，值得一提的是，我第一次看到"金榜题名"的"金榜"。</p>

<p>22.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041822.jpg" /></p>

<p>这张是科举考试的"试题"，题目非常长，深奥难懂，怪不得要考三天。</p>

<p>23.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041823.jpg" /></p>

<p>来到一楼，我发现这里正在举办"<a href="http://www.asihp.net/~museum/tw/exhibition.php?class_exhibion=149">稀世之珍----西北冈一OO一号大墓特展</a>"。这下我真的惊呆了，我原先觉得二楼的文物已经很珍贵了，但是与一楼相比，几乎不值一提。这里每一件都是无价的国宝，故宫博物院也看不到，是史语所最珍贵的收藏。更难得的是，那天下午，整个展厅只有我一个人，可以慢慢地、近距离地观赏。</p>

<p>24.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041824.jpg" /></p>

<p>20世纪初，中国学术界根据流传出来的甲骨，认定河南省安阳小屯村是3000多年前商朝最后一个都城。1934年，历史语言研究所发现，小屯村西北角的山冈是商朝的王室墓葬区。</p>

<p>25.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041825.jpg" /></p>

<p>这是小屯村的卫星地图。</p>

<p>26.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041826.jpg" /></p>

<p>在西北冈一共发现了八座商代帝王墓（<a href="http://maps.google.com/maps?t=h&hl=zh-CN&ie=UTF8&ll=36.139902,114.302895&spn=0.001798,0.005021&z=18&source=embed">google地图</a>）。</p>

<p>27.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041827.jpg" /></p>

<p>第一个挖掘的大墓，就被编号为1001号。后面发现，这是这八座商王墓中最大的一个。</p>

<p>28.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041828.jpg" /></p>

<p>1001号大墓呈十字形，东西南北四个方向皆有墓道，墓室位于中央。气势宏伟，堪与古埃及的帝王陵媲美。</p>

<p>29.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041829.jpg" /></p>

<p>这座大墓中发现了164个殉葬的头颅，是现存商王墓中最多的，有的历史学家推测，这座墓的主人是商王<a href="http://zh.wikipedia.org/zh/%E6%AD%A6%E4%B8%81">武丁</a>，否则不可能有那么多人陪葬。</p>

<p>30.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041830.jpg" /></p>

<p>1001号大墓出土了许多令人瞠目结舌的珍贵文物，现全部收藏于台湾的历史语言研究所。其中最令人称奇的，就是许多造型奇特的动物。上图是青铜器盖子上的一条龙。</p>

<p>31.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041831.jpg" /></p>

<p>玉雕的大象。</p>

<p>32.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041832.jpg" /></p>

<p>乌龟和青蛙。</p>

<p>33.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041833.jpg" /></p>

<p>大理石伏兽。</p>

<p>34.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041834.jpg" /></p>

<p>大理石立雕。</p>

<p>35.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041835.jpg" /></p>

<p>大理石老虎。</p>

<p>36.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041836.jpg" /></p>

<p>大理石鸟首。</p>

<p>37.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041837.jpg" /></p>

<p>大理石人身虎首。</p>

<p>38.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041838.jpg" /></p>

<p>人身虎首的侧面。</p>

<p>39.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041839.jpg" /></p>

<p>大理石猫头鹰。</p>

<p>40.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041840.jpg" /></p>

<p>大理石小鸟。</p>

<p>41.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041841.jpg" /></p>

<p>大理石牛。</p>

<p>42.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041842.jpg" /></p>

<p>还有一些非常夸张的人面造型。</p>

<p>43.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041843.jpg" /></p>

<p>看着这些奇特的文物，我心中浮现出了一个大大的问号。</p>

<p>目前，可以被验证的最早的中国朝代，就是商朝。再前面的三皇五帝和夏朝，纯属传说，根本找不到文物来证实。从这个意义上说，商朝（具体一点，安阳殷墟）就是中华文明的最早现身。</p>

<p>44.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041844.jpg" /></p>

<p>但是，看了上面这些雕刻，你觉得这像中华文明吗？</p>

<p>为什么商朝以后，这样奇特的、富有想象力和生命力的造型，再也没有出现过，中国人的艺术追求反而日趋刻板、精致、拘谨、苍白？</p>

<p>45.</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041845.jpg" /></p>

<p>春秋战国距离安阳殷墟的年代，大概只相差七八百年，但是艺术品的造型已经完全不同于商朝了，夸张的想象力再也看不到了，表现伦理、礼教、生活起居的内容越来越多。此后，中国人的想象力进一步衰退，如果不是佛教在汉代传入中国，古代中国人也许都不知道什么叫神话了。</p>

<p>为什么我们说敦煌壁画如此美丽动人？因为画的都是充满想象的佛教题材，中原文明根本没有这种内容。佛教传入之前，中国人对生、死、神、鬼的想象，简陋粗糙到完全可以忽略。</p>

<p>所以我们要问，为什么商朝人的艺术想象力没有传下来？</p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/04/museum_of_institute_of_history_and_philology.html">http://www.ruanyifeng.com/blog/2012/04/museum_of_institute_of_history_and_philology.html</a></li>
<li>最后修改时间：2012年5月13日 14:11</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>胡适的三个主义</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/04/hu_shih.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1719</id>

    <published>2012-04-13T06:35:30Z</published>
    <updated>2012-05-04T15:53:36Z</updated>

    <summary>来台湾之前，我就想好了，一定要去胡适纪念馆看看。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="World" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>来台湾之前，我就想好了，一定要去<a href="http://www.mh.sinica.edu.tw/koteki/">胡适纪念馆</a>看看。</p>]]>
        <![CDATA[<p><img src="http://image.beekka.com/blog/201204/bg2012041301.jpg" /></p>

<p>（图一，胡适，1891--1962。）</p>

<p>昨天终于成行，先坐捷运，到了位于南港的<a href="http://www.sinica.edu.tw/index.shtml">中央研究院</a>。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041302.jpg" /></p>

<p>（图二，中央研究院，台北市南港区研究院路二段128号。）</p>

<p>然后，按照<a href="http://maps.google.com/maps?q=%E8%83%A1%E9%80%82%E7%BA%AA%E5%BF%B5%E9%A6%86&hl=zh-TW&ie=UTF8&ll=25.04066,121.616163&spn=0.003111,0.005681&sll=25.04066,121.616346&sspn=0.003111,0.005681&t=h&hq=%E8%83%A1%E9%80%82%E7%BA%AA%E5%BF%B5%E9%A6%86&radius=15000&z=18">地图</a>，找到了西南角的"胡适纪念馆"。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041303.jpg" /></p>

<p>（图三，胡适纪念馆入口。）</p>

<p>=================================================</p>

<p>我喜欢胡适，是从大学期间阅读<a href="http://vip.book.sina.com.cn/book/index_40682.html">《胡适口述自传》</a>开始的。这本书让我大开眼界，意识到真正的学术不同于官方的意识形态，而是一种生动活泼、引人入胜的智力追求。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041304.jpg" /></p>

<p>（图四，《胡适口述自传》，唐德刚整理。）</p>

<p>后来，我大量阅读胡适的著作，断断续续读完了四卷本的《胡适文存》和一部分《胡适全集》。在治学方法和为人处事上，都深受他的影响。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041305.jpg" /></p>

<p>（图五，《胡适全集》，安徽人民出版社，44卷，2003年。）</p>

<p>在我看来，胡适的主要信念，可以总结为三个主义：实用主义、实验主义和自由主义。</p>

<p><strong>一、实用主义</strong></p>

<p>胡适师从"实用主义"大师杜威（John Dewey）。他完全继承了老师的主张，不提倡研究那些抽象的哲学思辨问题，而主要关注一些更实际的、与人自身相关的问题，注重实践和工具的重要性。</p>

<p>胡适最著名的一句话就是：</p>

<blockquote>

<p>"<strong>多研究些问题，少谈点主义。</strong>"</p>

</blockquote>

<p>胡适认为，具体的问题比抽象的主义更重要。</p>

<blockquote>

<p>"<strong>主义的危险，就是能使人心满意足，自以为寻着治病的根本方法，从此用不着费心力去研究这个那个具体问题的解决法了。</strong>"</p>

</blockquote>

<p>他主张年轻人要把自己的人生，用来解决实际的问题。</p>

<blockquote>

<p>"<strong>生命本没有意义，你要给它什么意义，它就有什么意义。与其终日冥想人生有何意义，不如试用此生做点有意义的事。</strong>"</p>

</blockquote>

<p><img src="http://image.beekka.com/blog/201204/bg2012041306.jpg" /></p>

<p>（图六，胡适纪念馆入口。）</p>

<p><strong>二、实验主义</strong></p>

<p>怎么解决实际的问题呢？胡适说，要用实验的方法，强调证据。</p>

<blockquote>

<p>"<strong>大胆的假设，小心的求证。</strong>"</p>

</blockquote>

<blockquote>

<p>"<strong>有几分证据说几分话，有七分证据不说八分话。</strong>"</p>

</blockquote>

<p>更重要的是，不要迂腐和迷信，要敢于怀疑。</p>

<blockquote>

<p>"<strong>读古人的书，一方面要知道古人聪明到怎样，一方面也要知道古人傻到怎样。</strong>"</p>

</blockquote>

<blockquote>

<p>"<strong>世间有一种最流行的迷信，叫做'服从多数的迷信'。人都以为多数人的公论总是不错的。</strong>"</p>

</blockquote>

<blockquote>

<p>"<strong>要用自己的头脑独立思考，不要轻易受人惑，不要轻易相信别人的理论，哪怕是我胡适说的话。</strong>"</p>

</blockquote>

<blockquote>

<p>"<strong>我这里千言万语，只是要教人一个不受人惑的方法。被孔丘、朱熹牵着鼻子走，固然不算高明；被马克思、列宁、斯大林牵着鼻子走，也算不得好汉。我自己决不想牵着谁的鼻子走。我只希望尽我的微薄的能力，教我的少年朋友们学一点防身的本领，努力做一个不受人惑的人。</strong>"</p>

</blockquote>

<p><img src="http://image.beekka.com/blog/201204/bg2012041307.jpg" /></p>

<p>（图七，胡适纪念馆陈列室。）</p>

<p><strong>三、自由主义</strong></p>

<p>胡适认为，一个有用的人必须思想自由，而一个强大的国家只可能是由无数自由的个人组成。</p>

<blockquote>

<p>"<strong>现在有人对你们说：'牺牲你们个人的自由，去求国家的自由！'我对你们说：'争取个人的自由，就是争取国家的自由；争取个人的人格，就是争取国家的国格！自由平等的国家不是一群奴才建造得起来的！'</strong>"</p>

</blockquote>

<blockquote>

<p>"<strong>把自己铸造成器，方才可以希望有益于社会。真实的为我，便是最有益的为人。把自己铸造成了自由独立的人格，你自然会不知足，不满意现状，敢说老实话。</strong>"</p>

</blockquote>

<blockquote>

<p>"<strong>我们所要建立的，是批评国民党的自由和批评孙中山的自由。上帝我们尚且可以批评，何况国民党和孙中山？</strong>"</p>

</blockquote>

<blockquote>

<p>"<strong>反自由不容忍。</strong>"</p>

</blockquote>

<p>在胡适看来，中国的封建礼教和专制主义，是自由的大敌。</p>

<blockquote>

<p>"<strong>中国社会最爱专制，往往用强力摧折个人的个性，压制个人自由独立的精神；等到个人的个性都消灭了，等到自由独立的精神都完了，中国社会自身也没有生气了，也不会进步了。</strong>"</p>

</blockquote>

<blockquote>

<p>"<strong>中国的教育，不但不能救亡，简直可以亡国。</strong>"</p>

</blockquote>

<blockquote>

<p>"<strong>明明是男盗女娼的社会，我们偏说是圣贤礼仪之邦；明明是赃官污吏的政治，我们偏要歌功颂德；明明是不可救药的大病，我们偏说一点病都没有！</strong>"</p>

</blockquote>

<p><img src="http://image.beekka.com/blog/201204/bg2012041308.jpg" /></p>

<p>（图八，胡适的卧室。）</p>

<p><strong>四、人生态度</strong></p>

<p>胡适用自己的行为，积极地实践上面三个信仰。</p>

<blockquote>

<p>"<strong>要怎么收获，先那么栽。</strong>"</p>

</blockquote>

<p>在为人处事上，他包容异己，乐于助人。</p>

<blockquote>

<p>"<strong>我受了十年的骂，从来不怨恨骂我的人。有时他们骂的不中肯，我反替他们着急。有时他们骂得太过火，反而损害骂者自己的人格，我更替他们不安。如果骂我而使骂者有益，便是我间接于他有恩了，我自然很愿挨骂。</strong>"</p>

</blockquote>

<blockquote>

<p>"<strong>待人时要在有疑处不疑，做学问要在不疑处有疑。</strong>"</p>

</blockquote>

<p>胡适的一生，历经晚清、民国、日本入侵、中共崛起等多个历史动荡时期，即使在最黑暗最困难的时候，他也对未来抱有信心，从不放弃和动摇。</p>

<blockquote>

<p>"<strong>我们要收将来的善果，必须努力种现在的新因。一粒一粒的种，必有满仓满屋的收成，这是我们今日应该有的信心。</strong></p>

<p><strong>我们要深信；今日的失败，都由于过去的不努力。</strong></p>

<p><strong>我们要深信；今日的努力，必定有将来的大收成。</strong></p>

<p><strong>佛典里有一句话："福不唐捐"。唐捐就是白白的丢了。我们也应该说："功不唐捐！"没有一点努力是会白白的丢了的。在我们看不见想不到的时候，在我们看不见想不到的方向，你瞧！你下的种子早已生根发叶开花结果了！"</strong></p>

</blockquote>

<p><img src="http://image.beekka.com/blog/201204/bg2012041309.jpg" /></p>

<p>（图九，胡适的会客厅。）</p>

<p>胡适很喜欢引用范仲淹的一句名言：</p>

<blockquote>

<p>"<strong>宁鸣而死，不默而生。</strong>"</p>

</blockquote>

<p>1962年年2月24日，中央研究院召开第五次院士会议。胡适不顾自己刚刚心脏病出院，参加了上午的会议，并且在晚上6点半出席了庆祝酒会。</p>

<p>在酒会上，他发表了即席演讲。不料讲到一半，突然脸色发白，倒在地上。送到医院后，终因心脏病突发，宣告不治，享年71岁。他用自己的生命实践了"宁鸣而死"。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041310.jpg" /></p>

<p>（图十，胡适去世当天的照片，可以看到他面容憔悴。）</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041311.jpg" /></p>

<p>（图十一，胡适突然倒地，溘然长逝。）</p>

<p>=========================================================</p>

<p>离开"胡适纪念馆"，走出中央研究院的大门，马路对面就是"胡适公园"。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041312.jpg" /></p>

<p>（图十二，胡适公园。）</p>

<p>首先映入眼帘的是一排喷水池，后面小山上的白色建筑就是胡适的墓地。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041313.jpg" /></p>

<p>（图十三，胡适的墓地位于土山之上。）</p>

<p>拾阶而上，就可以看到胡适、江冬秀夫妇的合葬墓。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041314.jpg" /></p>

<p>（图十四，胡适墓的入口。）</p>

<p>墓穴后面是蒋介石的题字"智德兼隆"。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041315.jpg" /></p>

<p>（图十五，胡适夫妇的墓碑。）</p>

<p>墓穴的右面，是胡适大儿子胡祖望的墓（2005年去世），以及二儿子胡思杜的纪念石。（胡思杜1948年从美国留学回国后，没有选择去台湾，而是留在大陆，迎接共产党。1950年，他在香港《大公报》发表《对我的父亲----胡适的批判》，公开表示与胡适划清界线。1957年反右运动中，他被定为右派，多次批斗后，不堪羞辱，上吊自杀。）</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041316.jpg" /></p>

<p>（图十六，胡适的两个儿子的墓碑。）</p>

<p>天色将暮，阴沉闷热的天空飘起了雨。静寂的墓园，再无旁人。入土将近50年的胡适先生与他的一位忠实读者，在这个亚热带岛屿的偏僻角落，一起默默地听着黄昏的雨声。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012041317.jpg" /></p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/04/hu_shih.html">http://www.ruanyifeng.com/blog/2012/04/hu_shih.html</a></li>
<li>最后修改时间：2012年5月 4日 23:53</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>函数式编程初探</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/04/functional_programming.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1718</id>

    <published>2012-04-06T07:18:15Z</published>
    <updated>2012-05-16T07:05:25Z</updated>

    <summary>诞生50多年之后，函数式编程（functional programming）开始获得越来越多的关注。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="IT" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>诞生50多年之后，<a href="http://en.wikipedia.org/wiki/Functional_programming">函数式编程</a>（functional programming）开始获得越来越多的关注。</p>]]>
        <![CDATA[<p>不仅最古老的函数式语言Lisp重获青春，而且新的函数式语言层出不穷，比如Erlang、clojure、Scala、F#等等。目前最当红的Python、Ruby、Javascript，对函数式编程的支持都很强，就连老牌的面向对象的Java、面向过程的PHP，都忙不迭地加入对匿名函数的支持。越来越多的迹象表明，函数式编程已经不再是学术界的最爱，开始大踏步地在业界投入实用。</p>

<p>也许继"面向对象编程"之后，"函数式编程"会成为下一个编程的主流范式（paradigm）。未来的程序员恐怕或多或少都必须懂一点。</p>

<p><img src="http://image.beekka.com/blog/201204/bg2012040601.png" style="border:none;" /></p>

<p>但是，"函数式编程"看上去比较难，缺乏通俗的入门教程，各种介绍文章都充斥着数学符号和专用术语，让人读了如坠云雾。就连最基本的问题"什么是函数式编程"，网上都搜不到易懂的回答。</p>

<p>下面是我的"函数式编程"学习笔记，分享出来，与大家一起探讨。内容不涉及数学（我也不懂<a href="http://en.wikipedia.org/wiki/Lambda_calculus">Lambda Calculus</a>），也不涉及高级特性（比如<a href="http://en.wikipedia.org/wiki/Lazy_evaluation">lazy evaluation</a>和<a href="http://en.wikipedia.org/wiki/Currying">currying</a>），只求尽量简单通俗地整理和表达，我现在所理解的"函数式编程"以及它的意义。</p>

<p>我主要参考了Slava Akhmechet的<em><a href="http://www.defmacro.org/ramblings/fp.html">"Functional Programming For The Rest of Us"</a></em>。</p>

<p><strong>一、定义</strong></p>

<p>简单说，"函数式编程"是一种<a href="http://en.wikipedia.org/wiki/Programming_paradigm">"编程范式"</a>（programming paradigm），也就是如何编写程序的方法论。</p>

<p>它属于<a href="http://en.wikipedia.org/wiki/Structured_programming">"结构化编程"</a>的一种，主要思想是把运算过程尽量写成一系列嵌套的函数调用。举例来说，现在有这样一个数学表达式：</p>

<blockquote>

<p>　　(1 + 2) * 3 - 4</p>

</blockquote>

<p>传统的过程式编程，可能这样写：</p>

<blockquote>

<p>　　var a = 1 + 2;</p>

<p>　　var b = a * 3;</p>

<p>　　var c = b - 4;</p>

</blockquote>

<p>函数式编程要求使用函数，我们可以把运算过程<a href="http://lostechies.com/derickbailey/2012/01/24/some-thoughts-on-functional-javascript/">定义</a>为不同的函数，然后写成下面这样：</p>

<blockquote>

<p>　　var result = subtract(multiply(add(1,2), 3), 4);</p>

</blockquote>

<p>这就是函数式编程。</p>

<p><strong>二、特点</strong></p>

<p>函数式编程具有五个鲜明的特点。</p>

<p><strong>1. 函数是"第一等公民"</strong></p>

<p>所谓<a href="http://en.wikipedia.org/wiki/First-class_function">"第一等公民"</a>（first class），指的是函数与其他数据类型一样，处于平等地位，可以赋值给其他变量，也可以作为参数，传入另一个函数，或者作为别的函数的返回值。</p>

<p>举例来说，下面代码中的print变量就是一个函数，可以作为另一个函数的参数。</p>

<blockquote>

<p>　　var print = function(i){ console.log(i);};<br />
 <br />
　　[1,2,3].forEach(print);</p>

</blockquote>

<p><strong>2. 只用"表达式"，不用"语句"</strong></p>

<p>"表达式"（expression）是一个单纯的运算过程，总是有返回值；"语句"（statement）是执行某种操作，没有返回值。函数式编程要求，只使用表达式，不使用语句。也就是说，每一步都是单纯的运算，而且都有返回值。</p>

<p>原因是函数式编程的开发动机，一开始就是为了处理运算（computation），不考虑系统的读写（I/O）。"语句"属于对系统的读写操作，所以就被排斥在外。</p>

<p>当然，实际应用中，不做I/O是不可能的。因此，编程过程中，函数式编程只要求把I/O限制到最小，不要有不必要的读写行为，保持计算过程的单纯性。</p>

<p><strong>3. 没有"副作用"</strong></p>

<p>所谓<a href="http://en.wikipedia.org/wiki/Side_effect_(computer_science)">"副作用"</a>（side effect），指的是函数内部与外部互动（最典型的情况，就是修改全局变量的值），产生运算以外的其他结果。</p>

<p>函数式编程强调没有"副作用"，意味着函数要保持独立，所有功能就是返回一个新的值，没有其他行为，尤其是不得修改外部变量的值。</p>

<p><strong>4. 不修改状态</strong></p>

<p>上一点已经提到，函数式编程只是返回新的值，不修改系统变量。因此，不修改变量，也是它的一个重要特点。</p>

<p>在其他类型的语言中，变量往往用来保存"状态"（state）。不修改变量，意味着状态不能保存在变量中。函数式编程使用参数保存状态，最好的例子就是递归。下面的代码是一个将字符串逆序排列的函数，它演示了不同的参数如何决定了运算所处的"状态"。</p>

<blockquote>

<p>　　function reverse(string) {</p>

<p>　　　　if(string.length == 0) {</p>

<p>　　　　　　return string;</p>

<p>　　　　} else {</p>

<p>　　　　　　return reverse(string.substring(1, string.length)) + string.substring(0, 1);</p>

<p>　　　　}</p>

<p>　　}</p>

</blockquote>

<p>由于使用了递归，函数式语言的运行速度比较慢，这是它长期不能在业界推广的主要原因。</p>

<p><strong>5. 引用透明</strong></p>

<p>引用透明（Referential transparency），指的是函数的运行不依赖于外部变量或"状态"，只依赖于输入的参数，任何时候只要参数相同，引用函数所得到的返回值总是相同的。</p>

<p>有了前面的第三点和第四点，这点是很显然的。其他类型的语言，函数的返回值往往与系统状态有关，不同的状态之下，返回值是不一样的。这就叫"引用不透明"，很不利于观察和理解程序的行为。</p>

<p><strong>三、意义</strong></p>

<p>函数式编程到底有什么好处，为什么会变得越来越流行？</p>

<p><strong>1. 代码简洁，开发快速</strong></p>

<p>函数式编程大量使用函数，减少了代码的重复，因此程序比较短，开发速度较快。</p>

<p>Paul Graham在<a href="http://www.ruanyifeng.com/docs/pg/">《黑客与画家》</a>一书中<a href="http://www.ruanyifeng.com/blog/2010/10/why_lisp_is_superior.html">写道</a>：同样功能的程序，极端情况下，Lisp代码的长度可能是C代码的二十分之一。</p>

<p>如果程序员每天所写的代码行数基本相同，这就意味着，"C语言需要一年时间完成开发某个功能，Lisp语言只需要不到三星期。反过来说，如果某个新功能，Lisp语言完成开发需要三个月，C语言需要写五年。"当然，这样的对比故意夸大了差异，但是"在一个高度竞争的市场中，即使开发速度只相差两三倍，也足以使得你永远处在落后的位置。"</p>

<p><strong>2. 接近自然语言，易于理解</strong></p>

<p>函数式编程的自由度很高，可以写出很接近自然语言的代码。</p>

<p>前文曾经将表达式(1 + 2) * 3 - 4，写成函数式语言：</p>

<blockquote>

<p>　　subtract(multiply(add(1,2), 3), 4)</p>

</blockquote>

<p>对它进行变形，不难得到另一种写法：</p>

<blockquote>

<p>　　add(1,2).multiply(3).subtract(4)</p>

</blockquote>

<p>这基本就是自然语言的表达了。再看下面的代码，大家应该一眼就能明白它的意思吧：</p>

<blockquote>

<p>　　merge([1,2],[3,4]).sort().search("2")</p>

</blockquote>

<p>因此，函数式编程的代码更容易理解。</p>

<p><strong>3. 更方便的代码管理</strong></p>

<p>函数式编程不依赖、也不会改变外界的状态，只要给定输入参数，返回的结果必定相同。因此，每一个函数都可以被看做独立单元，很有利于进行单元测试（unit testing）和除错（debugging），以及模块化组合。</p>

<p><strong>4. 易于"并发编程"</strong></p>

<p>函数式编程不需要考虑"死锁"（deadlock），因为它不修改变量，所以根本不存在"锁"线程的问题。不必担心一个线程的数据，被另一个线程修改，所以可以很放心地把工作分摊到多个线程，部署"并发编程"（concurrency）。</p>

<p>请看下面的代码：</p>

<blockquote>

<p>　　var s1 = Op1();</p>

<p>　　var s2 = Op2();</p>

<p>　　var s3 = concat(s1, s2);</p>

</blockquote>

<p>由于s1和s2互不干扰，不会修改变量，谁先执行是无所谓的，所以可以放心地增加线程，把它们分配在两个线程上完成。其他类型的语言就做不到这一点，因为s1可能会修改系统状态，而s2可能会用到这些状态，所以必须保证s2在s1之后运行，自然也就不能部署到其他线程上了。</p>

<p>多核CPU是将来的潮流，所以函数式编程的这个特性非常重要。</p>

<p><strong>5. 代码的热升级</strong></p>

<p>函数式编程没有副作用，只要保证接口不变，内部实现是外部无关的。所以，可以在运行状态下直接升级代码，不需要重启，也不需要停机。<a href="http://en.wikipedia.org/wiki/Erlang_(programming_language)">Erlang</a>语言早就证明了这一点，它是瑞典爱立信公司为了管理电话系统而开发的，电话系统的升级当然是不能停机的。</p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/04/functional_programming.html">http://www.ruanyifeng.com/blog/2012/04/functional_programming.html</a></li>
<li>最后修改时间：2012年5月16日 15:05</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>基于用户投票的排名算法（六）：贝叶斯平均</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_bayesian_average.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1717</id>

    <published>2012-03-28T11:48:55Z</published>
    <updated>2012-04-28T04:59:55Z</updated>

    <summary>（这个系列实在拖得太久，今天是最后一篇。）...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="IT" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>（这个系列实在拖得太久，今天是最后一篇。）</p>]]>
        <![CDATA[<p>上一篇介绍了<a href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_wilson_score_interval.html">"威尔逊区间"</a>，它解决了投票人数过少、导致结果不可信的问题。</p>

<p>举例来说，如果只有2个人投票，"威尔逊区间"的下限值会将赞成票的比例大幅拉低。这样做固然保证了排名的可信性，但也带来了另一个问题：排行榜前列总是那些票数最多的项目，新项目或者冷门的项目，很难有出头机会，排名可能会长期靠后。</p>

<p>以<a href="http://www.imdb.com/">IMDB</a>为例，它是世界最大的电影数据库，观众可以对每部电影投票，最低为1分，最高为10分。</p>

<p><a href="http://www.imdb.com/"><img src="http://image.beekka.com/blog/201203/bg2012032801.jpg" /></a></p>

<p>系统根据投票结果，计算出每部电影的平均得分。然后，再根据平均得分，排出最受欢迎的<a href="http://www.imdb.com/chart/top">前250名</a>的电影。</p>

<p><a href="http://www.imdb.com/chart/top"><img src="http://image.beekka.com/blog/201203/bg2012032802.png" /></a></p>

<p>这里就有一个问题：热门电影与冷门电影的平均得分，是否真的可比？举例来说，一部好莱坞大片有10000个观众投票，一部小成本的文艺片只有100个观众投票。这两者的投票结果，怎么比较？如果使用"威尔逊区间"，后者的得分将被大幅拉低，这样处理是否公平，能不能反映它们真正的质量？</p>

<p>一个合理的思路是，如果要比较两部电影的好坏，至少应该请同样多的观众观看和评分。既然文艺片的观众人数偏少，那么应该设法为它增加一些观众。</p>

<p>在<a href="http://www.imdb.com/chart/top">排名页面</a>的底部，IMDB给出了它的计算方法。</p>

<blockquote>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=WR%3D%5Cfrac%7Bv%7D%7Bv%2Bm%7DR%2B%5Cfrac%7Bm%7D%7Bv%2Bm%7DC&chs=60" style="border:none;" /></p>

<p>　　- WR， 加权得分（weighted rating）。<br />
　　- R，该电影的用户投票的平均得分（Rating）。<br />
　　- v，该电影的投票人数（votes）。<br />
　　- m，排名前250名的电影的最低投票数（现在为3000）。<br />
　　- C， 所有电影的平均得分（现在为6.9）。 </p>

</blockquote>

<p>仔细研究这个公式，你会发现，IMDB为每部电影增加了3000张选票，并且这些选票的评分都为6.9。这样做的原因是，假设所有电影都至少有3000张选票，那么就都具备了进入前250名的评选条件；然后假设这3000张选票的评分是所有电影的平均得分（即假设这部电影具有平均水准）；最后，用现有的观众投票进行修正，长期来看，v/(v+m)这部分的权重将越来越大，得分将慢慢接近真实情况。</p>

<p>这样做拉近了不同电影之间投票人数的差异，使得投票人数较少的电影也有可能排名前列。</p>

<p>把这个公式写成更一般的形式：</p>

<blockquote>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Cbar%7Bx%7D%3D%5Cfrac%7BC%5Ctimes%20m%2B%5CSigma%20%5E%7Bn%7D_%7Bi%3D1%7Dx_%7Bi%7D%7D%7Bn%2BC%7D&chs=80" style="border:none;" /></p>

<p>　　- C，投票人数扩展的规模，是一个自行设定的常数，与整个网站的总体用户人数有关，可以等于每个项目的平均投票数。<br />
　　- n，该项目的现有投票人数。<br />
　　- x，该项目的每张选票的值。<br />
　　- m，总体平均分，即整个网站所有选票的算术平均值。 </p>

</blockquote>

<p>这种算法被称为<a href="http://en.wikipedia.org/wiki/Bayesian_average">"贝叶斯平均"</a>（Bayesian average）。因为某种程度上，它借鉴了<a href="http://www.ruanyifeng.com/blog/2011/08/bayesian_inference_part_one.html">"贝叶斯推断"</a>（Bayesian inference）的思想：既然不知道投票结果，那就先估计一个值，然后不断用新的信息修正，使得它越来越接近正确的值。</p>

<p>在这个公式中，m（总体平均分）是"先验概率"，每一次新的投票都是一个调整因子，使总体平均分不断向该项目的真实投票结果靠近。投票人数越多，该项目的"贝叶斯平均"就越接近算术平均，对排名的影响就越小。</p>

<p>因此，这种方法可以给一些投票人数较少的项目，以相对公平的排名。</p>

<p>=================================================</p>

<p>"贝叶斯平均"也有缺点，主要问题是它假设用户的投票是正态分布。比如，电影A有10个观众评分，5个为五星，5个为一星；电影B也有10个观众评分，都给了三星。这两部电影的平均得分（无论是算术平均，还是贝叶斯平均）都是三星，但是电影A可能比电影B更值得看。</p>

<p>解决这个问题的思路是，假定每个用户的投票都是独立事件，每次投票只有n个选项可以选择，那么这就服从<a href="http://en.wikipedia.org/wiki/Multinomial_distribution">"多项分布"</a>（Multinomial distribution），就可以结合贝叶斯定理，估计该分布的期望值。由于这涉及复杂的统计学知识，这里就不深入了，感兴趣的朋友可以继续阅读William Morgan的<em><a href="http://masanjin.net/blog/how-to-rank-products-based-on-user-input">How to rank products based on user input</a></em>。</p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_bayesian_average.html">http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_bayesian_average.html</a></li>
<li>最后修改时间：2012年4月28日 12:59</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>基于用户投票的排名算法（五）：威尔逊区间</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_wilson_score_interval.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1716</id>

    <published>2012-03-19T18:49:45Z</published>
    <updated>2012-04-18T03:23:02Z</updated>

    <summary>迄今为止，这个系列都在讨论，如何给出&quot;某个时段&quot;的排名，比如&quot;过去24小时最热门的文章&quot;。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="IT" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>迄今为止，这个系列都在讨论，如何给出<strong>"某个时段"</strong>的排名，比如"过去24小时最热门的文章"。</p>]]>
        <![CDATA[<p>但是，很多场合需要的是<strong>"所有时段"</strong>的排名，比如"最受用户好评的产品"。</p>

<p>这时，时间因素就不需要考虑了。这个系列的最后两篇，就研究不考虑时间因素的情况下，如何给出排名。</p>

<p>一种常见的错误算法是：</p>

<blockquote>

<p>　　得分 = 赞成票 - 反对票</p>

</blockquote>

<p>假定有两个项目，项目A是60张赞成票，40张反对票，项目B是550张赞成票，450张反对票。请问，谁应该排在前面？按照上面的公式，B会排在前面，因为它的得分（550 - 450 = 100）高于A（60 - 40 = 20）。但是实际上，B的好评率只有55%（550 / 1000），而A为60%（60 / 100），所以正确的结果应该是A排在前面。</p>

<p>Urban Dictionary就是这种错误算法的实例。</p>

<p>　　<img src="http://image.beekka.com/blog/201203/bg2012032001.png" /></p>

<p>另一种常见的错误算法是</p>

<blockquote>

<p>　　得分 =  赞成票 / 总票数</p>

</blockquote>

<p>如果"总票数"很大，这种算法其实是对的。问题出在如果"总票数"很少，这时就会出错。假定A有2张赞成票、0张反对票，B有100张赞成票、1张反对票。这种算法会使得A排在B前面。这显然错误。</p>

<p>Amazon就是这种错误算法的实例。</p>

<p>　　<img src="http://image.beekka.com/blog/201203/bg2012032002.png" /></p>

<p>那么，正确的算法是什么呢？</p>

<p>我们先做如下设定：</p>

<blockquote>

<p>　　（1）每个用户的投票都是独立事件。</p>

<p>　　（2）用户只有两个选择，要么投赞成票，要么投反对票。</p>

<p>　　（3）如果投票总人数为n，其中赞成票为k，那么赞成票的比例p就等于k/n。</p>

</blockquote>

<p>如果你熟悉统计学，可能已经看出来了，这是一种统计分布，叫做<a href="http://en.wikipedia.org/wiki/Binomial_distribution">"二项分布"</a>（binomial distribution）。这很重要，下面马上要用到。</p>

<p>我们的思路是，p越大，就代表这个项目的好评比例越高，越应该排在前面。但是，p的可信性，取决于有多少人投票，如果样本太小，p就不可信。好在我们已经知道，p是"二项分布"中某个事件的发生概率，因此我们可以计算出p的置信区间。所谓<a href="http://zh.wikipedia.org/wiki/%E7%BD%AE%E4%BF%A1%E5%8C%BA%E9%97%B4">"置信区间"</a>，就是说，以某个概率而言，p会落在的那个区间。比如，某个产品的好评率是80%，但是这个值不一定可信。根据统计学，我们只能说，有95%的把握可以断定，好评率在75%到85%之间，即置信区间是[75%, 85%]。</p>

<p>这样一来，排名算法就比较清晰了：</p>

<blockquote>

<p>　　<strong>第一步，计算每个项目的"好评率"（即赞成票的比例）。</strong></p>

<p>　　<strong>第二步，计算每个"好评率"的置信区间（以95%的概率）。</strong></p>

<p>　　<strong>第三步，根据置信区间的下限值，进行排名。这个值越大，排名就越高。</strong></p>

</blockquote>

<p>这样做的原理是，置信区间的宽窄与样本的数量有关。比如，A有8张赞成票，2张反对票；B有80张赞成票，20张反对票。这两个项目的赞成票比例都是80%，但是B的置信区间（假定[75%, 85%]）会比A的置信区间（假定[70%, 90%]）窄得多，因此B的置信区间的下限值（75%）会比A（70%）大，所以B应该排在A前面。</p>

<p>置信区间的实质，就是进行可信度的修正，弥补样本量过小的影响。如果样本多，就说明比较可信，不需要很大的修正，所以置信区间会比较窄，下限值会比较大；如果样本少，就说明不一定可信，必须进行较大的修正，所以置信区间会比较宽，下限值会比较小。</p>

<p>二项分布的置信区间有多种计算公式，最常见的是<a href="http://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Normal_approximation_interval">"正态区间"</a>（Normal approximation interval），教科书里几乎都是这种方法。但是，它只适用于样本较多的情况（np > 5 且 n(1 − p) > 5），对于小样本，它的准确性很差。</p>

<p>1927年，美国数学家 Edwin Bidwell Wilson提出了一个修正公式，被称为<a href="http://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval">"威尔逊区间"</a>，很好地解决了小样本的准确性问题。</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Cfrac%7B%5Chat%7Bp%7D%2B%5Cfrac%7B1%7D%7B2n%7Dz%5E%7B2%7D_%7B1-%5Cfrac%7B%5Calpha%7D%7B2%7D%7D%5Cpm%20z_%7B1-%5Cfrac%7B%5Calpha%7D%7B2%7D%7D%5Csqrt%7B%5Cfrac%7B%5Chat%7Bp%7D(1-%5Chat%7Bp%7D)%7D%7Bn%7D%2B%5Cfrac%7Bz%5E%7B2%7D_%7B1-%5Cfrac%7B%5Calpha%7D%7B2%7D%7D%7D%7B4n%5E%7B2%7D%7D%7D%7D%7B1%2B%5Cfrac%7B1%7D%7Bn%7Dz%5E%7B2%7D_%7B1-%5Cfrac%7B%5Calpha%7D%7B2%7D%7D%7D&chs=180" style="border:none;" /></p>

<p>在上面的公式中，<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Chat%7Bp%7D&chs=20" style="border:none;" />表示样本的"赞成票比例"，n表示样本的大小，<img src="http://chart.googleapis.com/chart?cht=tx&chl=z_%7B1-%5Calpha%2F2%7D&chs=25" style="border:none;" />表示对应某个置信水平的z统计量，这是一个常数，可以通过查表或统计软件包得到。一般情况下，在95%的置信水平下，z统计量的值为1.96。</p>

<p>威尔逊置信区间的均值为</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Cfrac%7B%5Chat%7Bp%7D%2B%5Cfrac%7B1%7D%7B2n%7Dz%5E%7B2%7D_%7B1-%5Cfrac%7B%5Calpha%7D%7B2%7D%7D%7D%7B1%2B%5Cfrac%7B1%7D%7Bn%7Dz%5E%7B2%7D_%7B1-%5Cfrac%7B%5Calpha%7D%7B2%7D%7D%7D&chs=100" style="border:none;" /></p>

<p>它的下限值为</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Cfrac%7B%5Chat%7Bp%7D%2B%5Cfrac%7B1%7D%7B2n%7Dz%5E%7B2%7D_%7B1-%5Cfrac%7B%5Calpha%7D%7B2%7D%7D-z_%7B1-%5Cfrac%7B%5Calpha%7D%7B2%7D%7D%5Csqrt%7B%5Cfrac%7B%5Chat%7Bp%7D(1-%5Chat%7Bp%7D)%7D%7Bn%7D%2B%5Cfrac%7Bz%5E%7B2%7D_%7B1-%5Cfrac%7B%5Calpha%7D%7B2%7D%7D%7D%7B4n%5E%7B2%7D%7D%7D%7D%7B1%2B%5Cfrac%7B1%7D%7Bn%7Dz%5E%7B2%7D_%7B1-%5Cfrac%7B%5Calpha%7D%7B2%7D%7D%7D&chs=150" style="border:none;" /></p>

<p>可以看到，当n的值足够大时，这个下限值会趋向<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Chat%7Bp%7D&chs=20" style="border:none;" />。如果n非常小（投票人很少），这个下限值会大大小于<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Chat%7Bp%7D&chs=20" style="border:none;" />。实际上，起到了降低"赞成票比例"的作用，使得该项目的得分变小、排名下降。</p>

<p>Reddit的评论排名，目前就使用这个算法。</p>

<p>　　<img src="http://image.beekka.com/blog/201203/bg2012032003.png" /></p>

<p>[参考文献]</p>

<p>　　* <a href="http://www.evanmiller.org/how-not-to-sort-by-average-rating.html">How Not To Sort By Average Rating</a></p>

<p>（完）<br />
</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_wilson_score_interval.html">http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_wilson_score_interval.html</a></li>
<li>最后修改时间：2012年4月18日 11:23</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>基于用户投票的排名算法（四）：牛顿冷却定律</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_newton_s_law_of_cooling.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1715</id>

    <published>2012-03-15T16:31:52Z</published>
    <updated>2012-05-16T07:07:26Z</updated>

    <summary>这个系列的前三篇，介绍了Hacker News，Reddit和Stack Overflow的排名算法。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="IT" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>这个系列的前三篇，介绍了<a href="http://www.ruanyifeng.com/blog/2012/02/ranking_algorithm_hacker_news.html">Hacker News</a>，<a href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_reddit.html">Reddit</a>和<a href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_stack_overflow.html">Stack Overflow</a>的排名算法。</p>]]>
        <![CDATA[<p>今天，讨论一个更一般的数学模型。</p>

<p>这个系列的每篇文章，都是可以分开读的。但是，为了保证所有人都在同一页上，我再说一下，到目前为止，<strong>我们用不同方法，企图解决的都是同一个问题：根据用户的投票，决定最近一段时间内的"热文排名"。</strong></p>

<p>你可能会觉得，这是一个全新的课题，伴随着互联网而产生，需要全新的方法来解决。但是，实际上不是。我们可以把"热文排名"想象成一个"自然冷却"的过程：</p>

<blockquote>

<p>　　（1）任一时刻，网站中所有的文章，都有一个"当前温度"，温度最高的文章就排在第一位。</p>

<p>　　（2）如果一个用户对某篇文章投了赞成票，该文章的温度就上升一度。</p>

<p>　　（3）随着时间流逝，所有文章的温度都逐渐"冷却"。</p>

<p>　　<img src="http://image.beekka.com/blog/201203/bg2012031504.jpg" /></p>

</blockquote>

<p>这样假设的意义，在于我们可以照搬物理学的冷却定律，使用现成的公式，建立"温度"与"时间"之间的函数关系，轻松构建一个<a href="http://en.wikipedia.org/wiki/Exponential_decay">"指数式衰减"</a>（Exponential decay）的过程。</p>

<p><img src="http://image.beekka.com/blog/201203/bg2012031501.png" /></p>

<p>伟大的物理学家牛顿，早在17世纪就提出了温度冷却的数学公式，被后人称作<a href="http://episte.math.ntu.edu.tw/applications/ap_cooling/index.html">"牛顿冷却定律"</a>（Newton's Law of Cooling）。我们就用这个定律构建排名算法。</p>

<p><img src="http://image.beekka.com/blog/201203/bg2012031502.jpg" /></p>

<p>"牛顿冷却定律"非常简单，用一句话就可以概况：</p>

<blockquote>

<p><strong>物体的冷却速度，与其当前温度与室温之间的温差成正比。</strong></p>

</blockquote>

<p>写成数学公式就是：</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=T'(t)%3D-%5Calpha%20(T(t)-H)&chs=60" style="border:none;" /></p>

<p>其中，</p>

<blockquote>

<p>　　- T(t)是温度（T）的时间（t）函数。微积分知识告诉我们，温度变化（冷却）的速率就是温度函数的导数T'(t)。</p>

<p>　　- H代表室温，T(t)-H就是当前温度与室温之间的温差。由于当前温度高于室温，所以这是一个正值。</p>

<p>　　- 常数α（α>0）表示室温与降温速率之间的比例关系。前面的负号表示降温。不同的物质有不同的α值。</p>

</blockquote>

<p>这是一个微分方程，为了计算当前温度，需要求出T(t)的函数表达式。</p>

<p>第一步，改写方程，然后等式两边取积分。</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Cfrac%7BT'(t)%7D%7BT(t)-H%7D%3D-%5Calpha&chs=80" style="border:none;" /></p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Cint%5Cfrac%7BT'(t)%7D%7BT(t)-H%7D%5C%2Cdt%3D%5Cint(-%5Calpha)%5C%2Cdt&chs=80" style="border:none;" /></p>

<p><br />
第二步，求出这个积分的解（c为常数项）。</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=ln(T(t)-H)%3D-%5Calpha%20t%2Bc&chs=40" style="border:none;" /></p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=T(t)-H%3De%5E%7B(-%5Calpha%20t%2Bc)%7D&chs=40" style="border:none;" /></p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=T(t)%3DH%2BCe%5E%7B-%5Calpha%20t%7D&chs=40" style="border:none;" /></p>

<p>第三步，假定在时刻t<sub>0</sub>，该物体的温度是T(t<sub>0</sub>)，简写为T<sub>0</sub>。代入上面的方程，得到</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=T_%7B0%7D%3DH%2BCe%5E%7B-%5Calpha%20t_%7B0%7D%7D&chs=40" style="border:none;" /></p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=C%3D(T_%7B0%7D-H)e%5E%7B%5Calpha%20t_%7B0%7D%7D&chs=40" style="border:none;" /></p>

<p>第四步，将上一步的C代入第二步的方程。</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=T%3DH%2B(T_%7B0%7D-H)e%5E%7B-%5Calpha(t-t_%7B0%7D)%7D&chs=40" style="border:none;" /></p>

<p>假定室温H为0度，即所有物体最终都会"冷寂"，方程就可以简化为</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=T%3DT_%7B0%7De%5E%7B-%5Calpha(t-t_%7B0%7D)%7D&chs=40" style="border:none;" /></p>

<p>上面这个方程，就是我们想要的最终结果：</p>

<blockquote>

<p>　　<strong>本期温度 = 上一期温度 x exp(-(冷却系数) x 间隔的小时数)</strong></p>

</blockquote>

<p>将这个公式用在"排名算法"，就相当于（假定本期没有增加净赞成票）</p>

<blockquote>

<p>　　<strong>本期得分 = 上一期得分 x exp(-(冷却系数) x 间隔的小时数)</strong></p>

</blockquote>

<p>其中，"冷却系数"是一个你自己决定的值。如果假定一篇新文章的初始分数是100分，24小时之后"冷却"为1分，那么可以计算得到"冷却系数"约等于0.192。如果你想放慢"热文排名"的更新率，"冷却系数"就取一个较小的值，否则就取一个较大的值。</p>

<p><a href="http://www.wolframalpha.com/input/?i=plot%28100e%5E%28-0.19t%29%2C100e%5E%28-0.10t%29%2C100e%5E%28-0.50t%29%29+where+t%3D0..24"><img src="http://image.beekka.com/blog/201203/bg2012031503.jpg" /></a></p>

<p>[参考文献]</p>

<p>　　*　<a href="http://www.evanmiller.org/rank-hotness-with-newtons-law-of-cooling.html">Rank Hotness With Newton's Law of Cooling</a></p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_newton_s_law_of_cooling.html">http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_newton_s_law_of_cooling.html</a></li>
<li>最后修改时间：2012年5月16日 15:07</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>基于用户投票的排名算法（三）：Stack Overflow</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_stack_overflow.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1714</id>

    <published>2012-03-11T06:07:05Z</published>
    <updated>2012-04-17T03:37:54Z</updated>

    <summary>上一篇文章，我介绍了Reddit的排名算法。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="IT" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>上一篇文章，我介绍了<a href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_reddit.html">Reddit</a>的排名算法。</p>]]>
        <![CDATA[<p>它的特点是，用户可以投赞成票，也可以投反对票。也就是说，除了时间因素以外，只要考虑两个变量就够了。</p>

<p>但是，还有一些特定用途的网站，必须考虑更多的因素。世界排名第一的程序员问答社区<a href="http://stackoverflow.com/?tab=hot">Stack Overflow</a>，就是这样一个网站。</p>

<p><a href="http://stackoverflow.com/?tab=hot"><img src="http://image.beekka.com/blog/201203/bg2012031101.jpg" /></a></p>

<p>你在上面提出各种关于编程的问题，等待别人回答。访问者可以对你的问题进行投票（赞成票或反对票），表示这个问题是不是有价值。</p>

<p><img src="http://image.beekka.com/blog/201203/bg2012031102.png" /></p>

<p>一旦有人回答了你的问题，其他人也可以对这个回答投票（赞成票或反对票）。</p>

<p><img src="http://image.beekka.com/blog/201203/bg2012031103.png" /></p>

<p>排名算法的作用是，找出某段时间内的热点问题，即哪些问题最被关注、得到了最多的讨论。</p>

<p>在Stack Overflow的页面上，每个问题前面有三个数字，分别表示问题的得分、回答的数目和该问题的浏览次数。以这些变量为基础，就可以设计算法了。</p>

<p><img src="http://image.beekka.com/blog/201203/bg2012031104.png" /></p>

<p>创始人之一的Jeff Atwood，曾经在几年前，<a href="http://meta.stackoverflow.com/questions/11602/what-formula-should-be-used-to-determine-hot-questions">公布</a>过排名得分的计算公式。</p>

<p><img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Cfrac%7B(log_%7B10%7DQviews)%5Ctimes%204%2B%5Cfrac%7BQanswers%5Ctimes%20Qscore%7D%7B5%7D%2Bsum(Ascores)%7D%7B((Qage%2B1)-(%5Cfrac%7BQage-Qupdated%7D%7B2%7D))%5E%7B1.5%7D%7D&chs=120" style="border:none;" /></p>

<p>写成<a href="http://pastebin.com/FWJRbf1N">php代码</a>，就是下面这样：</p>

<p><a href="http://pastebin.com/FWJRbf1N"><img src="http://image.beekka.com/blog/201203/bg2012031105.png" /></a></p>

<p>各个算法变量的含义如下：</p>

<p><strong>（1）Qviews（问题的浏览次数）</strong></p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=(log_%7B10%7DQviews)%5Ctimes%204&chs=40" style="border:none;" /></p>

<p>某个问题的浏览次数越多，就代表越受关注，得分也就越高。这里使用了以10为底的对数，用意是当访问量越来越大，它对得分的影响将不断变小。</p>

<p><strong>（2）Qscore（问题得分）和Qanswers（回答的数量）</strong></p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=Qscore%20%5Ctimes%20%5Cfrac%7BQanswers%7D%7B5%7D&chs=60" style="border:none;" /></p>

<p>首先，Qscore（问题得分）= 赞成票-反对票。如果某个问题越受到好评，排名自然应该越靠前。</p>

<p>Qanswers表示回答的数量，代表有多少人参与这个问题。这个值越大，得分将成倍放大。这里需要注意的是，如果无人回答，Qanswers就等于0，这时Qscore再高也没用，意味着再好的问题，也必须有人回答，否则进不了热点问题排行榜。</p>

<p><strong>（3）Ascores（回答得分）</strong></p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=sum(Ascores)&chs=40" style="border:none;" /></p>

<p>一般来说，"回答"比"问题"更有意义。这一项的得分越高，就代表回答的质量越高。</p>

<p>但是我感觉，简单加总的设计还不够全面。这里有两个问题。首先，一个正确的回答胜过一百个无用的回答，但是，简单加总会导致，1个得分为100的回答与100个得分为1的回答，总得分相同。其次，由于得分会出现负值，因此那些特别差的回答，会拉低正确回答的得分。</p>

<p><strong>（4）Qage（距离问题发表的时间）和Qupdated（距离最后一个回答的时间）</strong></p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=((Qage%2B1)-(%5Cfrac%7BQage-Qupdated%7D%7B2%7D))%5E%7B1.5%7D&chs=60" style="border:none;" /></p>

<p>改写一下，可以看得更清楚：</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=(%5Cfrac%7BQage%7D%7B2%7D%2B%5Cfrac%7BQupdated%7D%7B2%7D%2B1)%5E%7B1.5%7D&chs=60" style="border:none;" /></p>

<p>Qage和Qupdated的单位都是秒。如果一个问题的存在时间越久，或者距离上一次回答的时间越久，Qage和Qupdated的值就相应增大。</p>

<p>也就是说，随着时间流逝，这两个值都会越变越大，导致分母增大，因此总得分会越来越小。</p>

<p><strong>（５）总结</strong></p>

<p>Stack Overflow热点问题的排名，与<strong>参与度</strong>（Qviews和Qanswers）和<strong>质量</strong>（Qscore和Ascores）成正比，与<strong>时间</strong>（Qage和Qupdated）成反比。</p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_stack_overflow.html">http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_stack_overflow.html</a></li>
<li>最后修改时间：2012年4月17日 11:37</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>基于用户投票的排名算法（二）：Reddit</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_reddit.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1713</id>

    <published>2012-03-07T08:24:29Z</published>
    <updated>2012-04-01T02:30:09Z</updated>

    <summary>（不好意思，这个系列中断了近两周，我会尽快在这几天，把后面几篇写完。）...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="IT" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>（不好意思，这个系列中断了近两周，我会尽快在这几天，把后面几篇写完。）</p>]]>
        <![CDATA[<p>上一次，我介绍了<a href="http://www.ruanyifeng.com/blog/2012/02/ranking_algorithm_hacker_news.html">Hacker News</a>的排名算法。它的特点是用户只能投赞成票，但是很多网站还允许用户投反对票。就是说，除了好评以外，你还可以给某篇文章差评。</p>

<p><a href="http://www.reddit.com/"><img src="http://image.beekka.com/blog/201203/bg2012030701.jpg" /></a></p>

<p><a href="http://www.reddit.com/">Reddit</a>是美国最大的网上社区，它的每个帖子前面都有向上和向下的箭头，分别表示"赞成"和"反对"。用户点击进行投票，Reddit根据投票结果，计算出最新的"热点文章排行榜"。</p>

<p>怎样才能将赞成票和反对票结合起来，计算出一段时间内最受欢迎的文章呢？如果文章A有100张赞成票、5张反对票，文章B有1000张赞成票、950张反对票，谁应该排在前面呢？</p>

<p>Reddit的程序是<a href="https://github.com/reddit/reddit">开源</a>的，使用Python语言编写。排名算法的<a href="http://pastebin.com/bygavdb7">代码</a>大致如下：</p>

<p><a href="http://pastebin.com/bygavdb7"><img src="http://image.beekka.com/blog/201203/bg2012030702.png" /></a></p>

<p>这段代码考虑了这样几个因素：</p>

<p>（1）帖子的新旧程度t</p>

<blockquote>

<p>　　t = 发贴时间 - 2005年12月8日7:46:43</p>

</blockquote>

<p>t的单位为秒，用unix时间戳计算。不难看出，一旦帖子发表，t就是固定值，不会随时间改变，而且帖子越新，t值越大。至于2005年12月8日，应该是Reddit成立的时间。</p>

<p>（2）赞成票与反对票的差x</p>

<blockquote>

<p>　　x = 赞成票 - 反对票 </p>

</blockquote>

<p>（3）投票方向y</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=y%3D%5Cbegin%7Bcases%7D%0A1%5Cqquad%5Cqquad%5Cqquad%5Cqquad%5Cqquad%5Cqquad(x%3E0)%5C%5C%0A0%5Cqquad%5Cqquad%5Cqquad%5Cqquad%5Cqquad%5Cqquad%20(x%3D0)%5C%5C%0A-1%5Cqquad(x%3C0)%0A%5Cend%7Bcases%7D&chs=100" style="border:none;" /></p>

<p>y是一个符号变量，表示对文章的总体看法。如果赞成票居多，y就是+1；如果反对票居多，y就是-1；如果赞成票和反对票相等，y就是0。</p>

<p>（4）帖子的受肯定（否定）的程度z</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=z%20%3D%20%0A%5Cbegin%7Bcases%7D%20%0A%7Cx%7C%2C%20%20%26%20%5Cmbox%7Bif%20%7Dx%5Cne0%5C%5C%0A1%2C%20%26%20%5Cmbox%7Bif%20%7Dx%3D0%20%0A%5Cend%7Bcases%7D&chs=80" style="border:none;" /></p>

<p>z表示赞成票与反对票之间差额的绝对值。如果对某个帖子的评价，越是一边倒，z就越大。如果赞成票等于反对票，z就等于1。</p>

<p>结合以上几个变量，Reddit的最终得分计算公式如下：</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=Score%3Dlog_%7B10%7Dz%2B%5Cfrac%7Byt%7D%7B45000%7D&chs=80" style="border:none;" /></p>

<p>这个公式可以分成两个部分来讨论：</p>

<p>（一） </p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=log_%7B10%7Dz&chs=50" style="border:none;" /></p>

<p>这个部分表示，赞成票与反对票的差额z越大，得分越高。</p>

<p>需要注意的是，这里用的是以10为底的对数，意味着z=10可以得到1分，z=100可以得到2分。也就是说，前10个投票人与后90个投票人（乃至再后面900个投票人）的权重是一样的，即如果一个帖子特别受到欢迎，那么越到后面投赞成票，对得分越不会产生影响。</p>

<p>当赞成票等于反对票，z=1，因此这个部分等于0，也就是不产生得分。</p>

<p>（二）</p>

<p>　　<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Cfrac%7Byt%7D%7B45000%7D&chs=80" style="border:none;" /></p>

<p>这个部分表示，t越大，得分越高，即新帖子的得分会高于老帖子。它起到自动将老帖子的排名往下拉的作用。</p>

<p>分母的45000秒，等于12.5个小时，也就是说，后一天的帖子会比前一天的帖子多得2分。结合前一部分，可以得到结论，如果前一天的帖子在第二天还想保持原先的排名，在这一天里面，它的z值必须增加100倍（净赞成票增加100倍）。</p>

<p>y的作用是产生加分或减分。当赞成票超过反对票时，这一部分为正，起到加分作用；当赞成票少于反对票时，这一部分为负，起到减分作用；当两者相等，这一部分为0。这就保证了得到大量净赞成票的文章，会排在前列；赞成票与反对票接近或相等的文章，会排在后面；得到净反对票的文章，会排在最后（因为得分是负值）。</p>

<p>（三）</p>

<p>这种算法的一个问题是，对于那些有争议的文章（赞成票和反对票非常接近），它们不可能排到前列。假定同一时间有两个帖子发表，文章A有1张赞成票（发帖人投的）、0张反对票，文章B有1000张赞成票、1000张反对票，那么A的排名会高于B，这显然不合理。</p>

<p><strong>结论就是，Reddit的排名，基本上由发帖时间决定，超级受欢迎的文章会排在最前面，一般性受欢迎的文章、有争议的文章都不会很靠前。</strong>这决定了Reddit是一个符合大众口味的社区，不是一个很激进、可以展示少数派想法的地方。</p>

<p>[参考资料]</p>

<p>　　* <a href="http://amix.dk/blog/post/19588">How Reddit ranking algorithms work </a></p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_reddit.html">http://www.ruanyifeng.com/blog/2012/03/ranking_algorithm_reddit.html</a></li>
<li>最后修改时间：2012年4月 1日 10:30</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>基于用户投票的排名算法（一）：Delicious和Hacker News</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/02/ranking_algorithm_hacker_news.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1712</id>

    <published>2012-02-24T13:50:24Z</published>
    <updated>2012-05-04T08:23:55Z</updated>

    <summary>互联网的出现，意味着&quot;信息大爆炸&quot;。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="IT" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>互联网的出现，意味着"信息大爆炸"。</p>]]>
        <![CDATA[<p>用户担心的，不再是信息太少，而是信息太多。如何从大量信息之中，快速有效地找出最重要的内容，成了互联网的一大核心问题。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012022401.jpg" /></p>

<p>各种各样的排名算法，是目前过滤信息的主要手段之一。对信息进行排名，意味着将信息按照重要性依次排列，并且及时进行更新。排列的依据，可以基于信息本身的特征，也可以基于用户的投票，即让用户决定，什么样的信息可以排在第一位。</p>

<p>下面，我将整理和分析一些基于用户投票的排名算法，打算分成六个部分连载，今天是第一篇。</p>

<p><strong>一、Delicious</strong></p>

<p>最直觉、最简单的算法，莫过于按照单位时间内用户的投票数进行排名。得票最多的项目，自然就排在第一位。</p>

<p>旧版的<a href="http://www.google.com/url?sa=D&q=http://del.icio.us/&usg=AFQjCNFp5KllThyYtlA74rqSRKdqRtAjxw">Delicious</a>，有一个"热门书签排行榜"，就是这样统计出来的。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012022402.png" /></p>

<p>它按照<strong>"过去60分钟内被收藏的次数"</strong>进行排名。每过60分钟，就统计一次。</p>

<p>这个算法的优点是比较简单、容易部署、内容更新相当快；缺点是，一方面，排名变化不够平滑，前一个小时还排名靠前的内容，往往第二个小时就一落千丈，另一方面，缺乏自动淘汰旧项目的机制，某些热门内容可能会长期占据排行榜前列。</p>

<p><strong>二、Hacker News</strong></p>

<p><a href="http://news.ycombinator.com/">Hacker News</a>是一个网络社区，可以张贴链接，或者讨论某个主题。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012022403.png" /></p>

<p>每个帖子前面有一个向上的三角形，如果你觉得这个内容很好，就点击一下，投上一票。根据得票数，系统自动统计出热门文章排行榜。但是，并非得票最多的文章排在第一位，还要考虑时间因素，新文章应该比旧文章更容易得到好的排名。</p>

<p>Hacker News使用Paul Graham开发的Arc语言编写，源码可以从<a href="http://arclanguage.org/">arclanguage.org</a>下载。它的排名算法是<a href="http://pastebin.com/ZF57qQPi">这样</a>实现的：</p>

<p><a href="http://pastebin.com/ZF57qQPi"><img src="http://image.beekka.com/blog/201202/bg2012022404.png" /></a></p>

<p>将上面的代码还原为数学公式：</p>

<p><img src="http://chart.googleapis.com/chart?cht=tx&chl=Score%3D%5Cfrac%7BP-1%7D%7B(T%2B2)%5E%7BG%7D%7D&chs=60" style="border:none;" /></p>

<p>其中，</p>

<p>　　P表示帖子的得票数，减去1是为了忽略发帖人的投票。</p>

<p>　　T表示距离发帖的时间（单位为小时），加上2是为了防止最新的帖子导致分母过小（之所以选择2，可能是因为从原始文章出现在其他网站，到转贴至Hacker News，平均需要两个小时）。</p>

<p>　　G表示"重力因子"（gravityth power），即将帖子排名往下拉的力量，默认值为1.8，后文会详细讨论这个值。</p>

<p>从这个公式来看，决定帖子排名有三个因素：</p>

<p><strong>第一个因素是得票数P。</strong></p>

<p>在其他条件不变的情况下，得票越多，排名越高。</p>

<p><a href="http://www.wolframalpha.com/input/?i=plot(+(30+-+1)+%2F+(t+%2B+2)%5E1.8%2C++(60+-+1)+%2F+(t+%2B+2)%5E1.8%2C+(200+-+1)+%2F+(t+%2B+2)%5E1.8+)+where+t%3D0..24"><img src="http://image.beekka.com/blog/201202/bg2012022405.png" /></a></p>

<p>从<a href="http://www.wolframalpha.com/input/?i=plot(+(30+-+1)+%2F+(t+%2B+2)%5E1.8%2C++(60+-+1)+%2F+(t+%2B+2)%5E1.8%2C+(200+-+1)+%2F+(t+%2B+2)%5E1.8+)+where+t%3D0..24">上图</a>可以看到，有三个同时发表的帖子，得票分别为200票、60票和30票（减1后为199、59和29），分别以黄色、紫色和蓝色表示。在任一个时间点上，都是黄色曲线在最上方，蓝色曲线在最下方。</p>

<p>如果你不想让"高票帖子"与"低票帖子"的差距过大，可以在得票数上加一个小于1的指数，比如(P-1)^0.8。</p>

<p><strong>第二个因素是距离发帖的时间T。</strong></p>

<p>在其他条件不变的情况下，越是新发表的帖子，排名越高。或者说，一个帖子的排名，会随着时间不断下降。</p>

<p>从前一张图可以看到，经过24小时之后，所有帖子的得分基本上都小于1，这意味着它们都将跌到排行榜的末尾，保证了排名前列的都将是较新的内容。</p>

<p><strong>第三个因素是重力因子G。</strong></p>

<p>它的数值大小决定了排名随时间下降的速度。</p>

<p><a href="http://www.wolframalpha.com/input/?i=plot%28+%28p+-+1%29+%2F+%28t+%2B+2%29%5E2.0%2C++%28p+-+1%29+%2F+%28t+%2B+2%29%5E1.8%2C+%28p+-+1%29+%2F+%28t+%2B+2%29%5E1.5+%29+where+t%3D0..24%2C+p%3D10"><img src="http://image.beekka.com/blog/201202/bg2012022406.png" /></a></p>

<p>从<a href="http://www.wolframalpha.com/input/?i=plot%28+%28p+-+1%29+%2F+%28t+%2B+2%29%5E2.0%2C++%28p+-+1%29+%2F+%28t+%2B+2%29%5E1.8%2C+%28p+-+1%29+%2F+%28t+%2B+2%29%5E1.5+%29+where+t%3D0..24%2C+p%3D10">上图</a>可以看到，三根曲线的其他参数都一样，G的值分别为1.5、1.8和2.0。G值越大，曲线越陡峭，排名下降得越快，意味着排行榜的更新速度越快。</p>

<p>知道了算法的构成，就可以调整参数的值，以适用你自己的应用程序。</p>

<p><strong>[参考文献]</strong></p>

<p>　　* <a href="http://amix.dk/blog/post/19574">How Hacker News ranking algorithm works</a></p>

<p>　　* <a href="http://blog.linkibol.com/2010/05/07/how-to-build-a-popularity-algorithm-you-can-be-proud-of/">How to Build a Popularity Algorithm You can be Proud of</a></p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/02/ranking_algorithm_hacker_news.html">http://www.ruanyifeng.com/blog/2012/02/ranking_algorithm_hacker_news.html</a></li>
<li>最后修改时间：2012年5月 4日 16:23</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>墙上的44句话</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/02/44_weeks_of_words.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1711</id>

    <published>2012-02-17T11:36:14Z</published>
    <updated>2012-04-08T08:35:50Z</updated>

    <summary>2010年，芬兰艺术家Mikko Kuorinki做了一件独特的艺术品。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="Music_and_Art" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>2010年，芬兰艺术家<a href="http://www.kuorinki.com">Mikko Kuorinki</a>做了一件独特的艺术品。</p>]]>
        <![CDATA[<p><img src="http://image.beekka.com/blog/201202/bg2012021711.jpg" /></p>

<p>他在赫尔辛基的<a href="http://www.kiasma.fi/">奇亚斯玛当代艺术博物馆</a>（Kiasma museum），找了一堵墙，装了一个175 x 320cm的木架子，上面用不同的字母组合出一句话。每周换一次内容，一共持续了<a href="http://www.kuorinki.com/works/wall-piece-with-200-letters-kiasma/">44周</a>。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021713.jpg" /></p>

<p>这个作品的用意在于，完全剥离了外在形式，只呈现语言的基本内容，让观众与文字背后的思想直接面对面，感受词语带来的力量。这种独特的形式，取得了意想不到的效果，很多人经过它的时候，都不由自主停下脚步，仔细观看。</p>

<p>我很喜欢这个作品，简洁的形式表达出丰富的内涵。下面就是这44句话中，我最喜欢的10句话。我梦想有一天，自己也可以在上海的地铁站里，做一个中文版。</p>

<p>（预告：本文结尾处，我要做一个广告，请一直往下读。）</p>

<p>1.</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021701.jpg" /></p>

<p><strong>If you were alone, you would cut yourself in two, so that one part would shape the other.</strong></p>

<p><strong>如果你感到孤独，请把自己一切为二，一个半边就有另一个半边陪伴。</strong></p>

<p>出处：Elias Canetti,  The Human Province  (1973)</p>

<p>2. </p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021702.jpg" /></p>

<p><strong>Looking in the mirror is like asking stranger for directions.</strong></p>

<p><strong>照镜子就像向一个陌生人问路。</strong></p>

<p>出处：Ronald Koertge, 12 Photographs  of Yellowstone (1976)</p>

<p>3. </p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021703.jpg" /></p>

<p><strong>My fake plants died, because I did not pretend to water them.</strong></p>

<p><strong>我的假花死了，因为我没有假装给它们浇水。</strong></p>

<p>出处：Mitch Hedberg, Mitch All Together (2003)</p>

<p>4. </p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021704.jpg" /></p>

<p><strong>In the struggle between yourself and the world, second the world.</strong></p>

<p><strong>当你与社会发生冲突，请站在社会这一边。</strong></p>

<p>出处：Franz Kafka,  Unpublished Works 1916-1918</p>

<p>5. </p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021705.jpg" /></p>

<p><strong>Sometimes everything seems so... OH, I don't know</strong></p>

<p><strong>有时，一切看起来如此......哦，我也不知道</strong></p>

<p>出处：Joe Brainard,  Poem (1971)  </p>

<p>6. </p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021706.jpg" /></p>

<p><strong>Without a sense of identity, there can be no real struggle.</strong></p>

<p><strong>如果没有清晰的自我意识，也就不存在真正的抗争。</strong></p>

<p>出处：Paulo Freire, Pedagogy of the Oppressed (1970)</p>

<p>7. </p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021707.jpg" /></p>

<p><strong>Pleasure may come from illusion, but happiness can come only of reality.</strong></p>

<p><strong>欢愉也许来自幻觉，但幸福只能来自现实。</strong></p>

<p>出处：Nicolas Chamfort  </p>

<p>8. </p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021708.jpg" /></p>

<p><strong>We must travel in the direction of our fear.</strong></p>

<p><strong>我们恐惧的地方，就是应该探索的地方。</strong></p>

<p>出处：John Berryman  </p>

<p>9. </p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021709.jpg" /></p>

<p><strong>I want to keep smashing myself until I am whole.</strong></p>

<p><strong>我要不停地粉碎自己，直到变得完整。</strong></p>

<p>出处：Elias Canetti, The Human Province  (1973)</p>

<p>10. </p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021710.jpg" /></p>

<p><strong>In the morning, there is meaning.</strong></p>

<p><strong>在早晨，你能找到意义。</strong></p>

<p>出处：Gertrude Stein, Tender Buttons (1914)</p>

<p>=================================================</p>

<p>下面是广告时间。</p>

<p>去年9月，我转贴了<a href="http://www.ruanyifeng.com/blog/2011/09/birth_of_sisi.html">《思思诞生记》</a>，请大家帮忙，为我认识10年的好朋友<a href="http://blog.bomoo.com/pin/">Pin</a>介绍工作。</p>

<p>现在，Pin即将告别半岁的女儿，独自到深圳的一家外贸公司上班。为了多挣奶粉钱，上班之余，她开了一家淘宝店，专营菲律宾进口的<a href="http://item.taobao.com/item.htm?id=13722630566">7D芒果干</a>。</p>

<p>我在这里为她的<a href="http://shop70350073.taobao.com/">淘宝店</a>做广告。如果你需要休闲食品，欢迎购买Pin销售的7D芒果干：<a href="http://shop70350073.taobao.com/">http://shop70350073.taobao.com/</a>。</p>

<p>不仅因为这是世界上最有名、最好吃的芒果干，还因为这样可以帮到一个失去父亲、也没有母亲在身边的半岁女婴。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021712.jpg" /></p>

<p>作为10年的朋友，我深知Pin的人品，对她销售的产品非常有信心。我敢以人格担保，这些都是菲律宾原产的正品，绝无假冒伪劣之虞。如果有人问起，为什么淘宝上还有一些价格低得多的相同商品，Pin发给我一张照片，这是她在菲律宾超市拍的。你可以根据菲律宾比索的汇率算一下，正品在原产地是什么<a href="http://www.google.com.hk/search?hl=zh-CN&newwindow=1&safe=strict&q=59.50%E8%8F%B2%E5%BE%8B%E5%AE%BE%E6%AF%94%E7%B4%A2%E7%AD%89%E4%BA%8E%E5%A4%9A%E5%B0%91%E4%BA%BA%E6%B0%91%E5%B8%81&oq=59.50%E8%8F%B2%E5%BE%8B%E5%AE%BE%E6%AF%94%E7%B4%A2%E7%AD%89%E4%BA%8E%E5%A4%9A%E5%B0%91%E4%BA%BA%E6%B0%91%E5%B8%81&aq=f&aqi=&aql=&gs_sm=3&gs_upl=394394l431764l0l432094l45l31l1l0l0l0l331l590l2-1.1l3l0">价格</a>。</p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/02/44_weeks_of_words.html">http://www.ruanyifeng.com/blog/2012/02/44_weeks_of_words.html</a></li>
<li>最后修改时间：2012年4月 8日 16:35</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>网页开发的6种在线调试环境</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/02/6_online_playgrounds_for_web_developing.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1710</id>

    <published>2012-02-13T08:28:30Z</published>
    <updated>2012-04-01T01:16:21Z</updated>

    <summary>如今的网页代码，一般由三个部分组成：...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="IT" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>如今的网页代码，一般由三个部分组成：</p>]]>
        <![CDATA[<blockquote>

<p>　　* HTML，语义层，提供网页的内容。</p>

<p>　　* CSS，表现层，规定网页的外观。</p>

<p>　　* Javascript，动作层，定义用户与网页的互动。</p>

</blockquote>

<p>理想的开发环境，应该既可以分别调试这三种代码，又可以轻松查看它们合并在一起的整体效果。</p>

<p>浏览器是最合适的效果查看工具，所以很多人想到，代码调试环境也可以直接部署在浏览器中，以网站的形式提供服务。</p>

<p>下面，我根据<a href="http://designshack.net/articles/css/5-online-playgrounds-for-html-css-and-javascript-compared/">Design Shack</a>的文章，总结一下目前最常见的6种网页开发在线调试环境。它们大大方便了网页设计师的工作，极大地提供了工作效率。</p>

<p><strong>一、CSSDesk</strong></p>

<p>网址：<a href="http://cssdesk.com/">http://cssdesk.com/</a> （需翻墙）</p>

<p><a href="http://cssdesk.com/"><img src="http://image.beekka.com/blog/201202/bg2012021301.jpg" /></a></p>

<p>这个网站是最早出现的在线调试环境之一，主要用于调试CSS。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021302.jpg" /></p>

<p>左侧两个面板，可以分别输入html和css代码，但不支持Javascript调试。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021303.jpg" /></p>

<p>你可以改变"预览区"的背景颜色，可以保存或下载调试完成的代码。</p>

<p><strong>二、Dabblet</strong></p>

<p>网址：<a href="http://dabblet.com/">http://dabblet.com/</a></p>

<p><a href="http://dabblet.com/"><img src="http://image.beekka.com/blog/201202/bg2012021304.jpg" /></a></p>

<p>Dabblet也是一个CSS调试环境，不支持Javascript调试。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021305.jpg" /></p>

<p>它将网页效果分成"CSS效果"、"HTML效果"和"整体效果"三个面板，方便单独调试。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021306.jpg" /></p>

<p>它最大的特点有两个，一是动态显示代码效果，代码一输入，效果就自动显示出来；二是显示CSS提示，比如上图的字体效果和长度效果。</p>

<p><strong>三、JS Bin</strong></p>

<p>网址：<a href="http://jsbin.com">http://jsbin.com</a></p>

<p><a href="http://jsbin.com"><img src="http://image.beekka.com/blog/201202/bg2012021307.jpg" /></a></p>

<p>这是一个较早出现的Javascript在线调试环境。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021308.jpg" /></p>

<p>它分成Javascript、html和"效果预览"三个区域，你可以自行勾选显示哪些区域。它没有独立的CSS代码区，CSS代码必须嵌入html代码，这点很不方便。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021309.jpg" /></p>

<p>它支持加载常用的Javascript库。除此以外，其他特色不多。</p>

<p><strong>四、jsFiddle</strong></p>

<p>网址：<a href="http://jsfiddle.net/">http://jsfiddle.net/</a></p>

<p><a href="http://jsfiddle.net/"><img src="http://image.beekka.com/blog/201202/bg2012021310.jpg" /></a></p>

<p>jsFiddle是目前最受欢迎的在线调试环境。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021311.jpg" /></p>

<p>它的默认界面分成5个区域，左边是参数设置，右边依次是HTML、Javascript、CSS和"效果预览区"。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021312.jpg" /></p>

<p>除了加载常见的Javascript库，它还支持SCSS代码和CoffeeScript代码。你甚至可以把它的窗口嵌入自己的网页。</p>

<p><strong>五、Tinkerbin</strong></p>

<p>网址：<a href="http://tinkerbin.com/">http://tinkerbin.com/</a></p>

<p><a href="http://tinkerbin.com/"><img src="http://image.beekka.com/blog/201202/bg2012021313.jpg" /></a></p>

<p>Tinkerbin很像jsFiddle，也是分成HTML、Javascript、CSS和"效果预览区"。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021314.jpg" /></p>

<p>它的特点在于，你可以选择某种代码独占整个编辑区，这样就增大了代码编辑的可视空间。另外，它可以实时显示代码运行结果，这是jsFiddle不支持的。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021315.jpg" /></p>

<p>它支持的代码种类相当多，比如 HAML、SCSS、LESS和CoffeeScript。</p>

<p><strong>六、Rendur</strong></p>

<p>网址：<a href="http://rendur.com/">http://rendur.com/</a></p>

<p><a href="http://rendur.com/"><img src="http://image.beekka.com/blog/201202/bg2012021316.jpg" /></a></p>

<p>Rendur是一个轻量级在线调试环境，功能不多，但是加载和运行都很快。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012021317.jpg" /></p>

<p>用户可以在HTML、CSS、Javascript三个面板中切换，输入相应代码。代码的运行结果，会自动显示在背景网页上。最后一个面板，显示的是整个网页的源码。</p>

<p>（完）</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/02/6_online_playgrounds_for_web_developing.html">http://www.ruanyifeng.com/blog/2012/02/6_online_playgrounds_for_web_developing.html</a></li>
<li>最后修改时间：2012年4月 1日 09:16</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

<entry>
    <title>Unix目录结构的来历</title>
    <link rel="alternate" type="text/html" href="http://www.ruanyifeng.com/blog/2012/02/a_history_of_unix_directory_structure.html" />
    <id>tag:www.ruanyifeng.com,2012:/blog//1.1709</id>

    <published>2012-02-06T04:50:03Z</published>
    <updated>2012-02-17T03:08:50Z</updated>

    <summary>Unix（包含Linux）的初学者，常常会很困惑，不明白目录结构的含义何在。...</summary>
    <author>
        <name>阮一峰</name>
        <uri>http://www.ruanyifeng.com</uri>
    </author>
    
        <category term="IT" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.ruanyifeng.com/blog/">
        <![CDATA[<p>Unix（包含Linux）的初学者，常常会很困惑，不明白目录结构的含义何在。</p>]]>
        <![CDATA[<p><img src="http://image.beekka.com/blog/201202/bg2012020601.jpg" /></p>

<p>举例来说，根目录下面有一个子目录/bin，用于存放二进制程序。但是，/usr子目录下面还有/usr/bin，以及/usr/local/bin，也用于存放二进制程序；某些系统甚至还有/opt/bin。它们有何区别？</p>

<p>长久以来，我也感到很费解，不明白为什么这样设计。像大多数人一样，我只是根据<a href="http://www.pathname.com/fhs/pub/fhs-2.3.html">《Unix文件系统结构标准》</a>（Filesystem Hierarchy Standard），死记硬背不同目录的区别。</p>

<p>昨天，我读到了Rob Landley的<a href="http://lists.busybox.net/pipermail/busybox/2010-December/074114.html">简短解释</a>，这才恍然大悟，原来Unix目录结构是历史造成的。</p>

<p>话说1969年，<a href="http://www.ruanyifeng.com/blog/2009/06/unix_turns_40.html">Ken Thompson</a>和<a href="http://www.ruanyifeng.com/blog/2011/10/dennis_ritchie.html">Dennis Ritchie</a>在小型机PDP-7上发明了Unix。1971年，他们将主机升级到了PDP-11。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012020602.jpg" /></p>

<p>当时，他们使用一种叫做RK05的储存盘，一盘的容量大约是1.5MB。</p>

<p><img src="http://image.beekka.com/blog/201202/bg2012020603.jpg" /></p>

<p>没过多久，操作系统（根目录）变得越来越大，一块盘已经装不下了。于是，他们加上了第二盘RK05，并且规定第一块盘专门放系统程序，第二块盘专门放用户自己的程序，因此挂载的目录点取名为/usr。也就是说，根目录"/"挂载在第一块盘，"/usr"目录挂载在第二块盘。除此之外，两块盘的目录结构完全相同，第一块盘的目录（/bin,  /sbin, /lib, /tmp...）都在/usr目录下重新出现一次。</p>

<p>后来，第二块盘也满了，他们只好又加了第三盘RK05，挂载的目录点取名为/home，并且规定/usr用于存放用户的程序，/home用于存放用户的数据。</p>

<p>从此，这种目录结构就延续了下来。随着硬盘容量越来越大，各个目录的含义进一步得到明确。</p>

<p>　　<strong>/</strong>：存放系统程序，也就是At&t开发的Unix程序。</p>

<p>　　<strong>/usr</strong>：存放Unix系统商（比如IBM和HP）开发的程序。</p>

<p>　　<strong>/usr/local</strong>：存放用户自己安装的程序。</p>

<p>　　<strong>/opt</strong>：在某些系统，用于存放第三方厂商开发的程序，所以取名为option，意为"选装"。</p>

<p>（完）<br />
</p>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;border:1px solid #d3d3d3;margin:1em;background-color:#AAD2F0;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><h3>文档信息</h3>
<ul>
<li>版权声明：自由转载-非商用-非衍生-保持署名 | <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">Creative Commons BY-NC-ND 3.0</a></li>
<li>原文网址：<a href="http://www.ruanyifeng.com/blog/2012/02/a_history_of_unix_directory_structure.html">http://www.ruanyifeng.com/blog/2012/02/a_history_of_unix_directory_structure.html</a></li>
<li>最后修改时间：2012年2月17日 11:08</li>
<li>付费支持：<a href="https://mai.alipay.com/p.htm?id=2012033102826278" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/rmb_32.png" alt="支付宝担保交易" style="border:none;vertical-align:middle;" /></a> | <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yifeng.ruan@gmail.com&currency_code=USD&amount=2.99&return=http://www.ruanyifeng.com/thank.html&item_name=Ruan%20YiFeng's%20Blog&undefined_quantity=1&no_note=0" target="_blank"><img src="http://www.ruanyifeng.com/blog/images/dollar_32.png"  alt="paypal" style="border:none;vertical-align:middle;" /></a> </li>
</ul></div>]]>
        <![CDATA[<div style="color:#556677;line-height:160%;padding:0.3em 0.5em;margin:1em;-moz-border-radius: 10px;-webkit-border-radius:10px;border-radius: 10px;"><p><a href="http://yipinzao.com/" target="_blank" style="border:none;"><img src="http://www.ruanyifeng.com/blog/images/ad_yipinzao.jpg" style="border:none;"></a>
</p></div>]]>
    </content>
</entry>

</feed>

