May 13, 2009 - 编程珠玑番外篇-D. 高级语言怎么来的-1

Comments

终于放暑假了, 有心情来八卦了. 我主要想八卦一下高级语言的设计思想和各种范式的来龙去脉, 也就是回答这个问题: 编程语言为什么会发生成现在这个样子哩? 这里面的奥妙又在哪里哩? 我尝试着把这个系列的八卦写下去, 包括虚拟机的设计, 线程的设计, 栈和寄存器两大流派的来龙去脉等等, 也算是完成年初给大家许下的诺言.

高级编程语言的创始纪上写道:”初, 世间无语言, 仅电路与连线. 及大牛出, 天地开, 始有FORTRAN, LISP. ALGOL 随之, 乃有万种语.” 我们都知道, LISP 是基于递归函数的, FORTRAN 是做科学计算的. 现在的C 等等, 都比较像 FORTRAN 不像 LISP. 可是很少有人知道, 最初, FORTRAN 是不支持函数递归调用的, 而LISP是一生下来就支持的, 所有高级语言里面的递归调用, 都是逐渐从 LISP 那里学来的. 这段尘封的历史非常有趣, 值得八卦一番.

一般人学编程, 除了写 Hello World 之外, 人生写的第二个程序, 不是阶乘就是菲波拉契数列, 要不就是汉洛塔. 而这几个程序, 基本上都是因为函数的递归调用才显得简单漂亮. 没有递归的日子里, 人民非常想念您. 可是, 第一版的 FORTRAN 就居然居然不支持递归. 细心的读者要问了, 不支持递归的语言能图灵完全么? 当然可以, 图灵机就是没递归的典型的例子. 但是没递归调用的程序会很难写, 尤其像汉诺塔这种. 那么, FORTRAN 他怎么就悍然不支持递归呢, 让我们回到 1960 年.

话说当年, IBM 是计算机行业的领军者. 那时候的计算机, 都是比柜子还大的大家伙, 至于计算能力嘛, 却比你的手机还弱. 那时候计算机所做的最多的事情, 不是发邮件打游戏, 而是作计算. 作计算嘛, 自然需要一种和数学语言比较接近的编程语言. 于是, 1960年, IBM 就捣鼓出了 FORTRAN, 用行话说, 就是公式翻译系统. 这个公式翻译系统, 就成了世界上第一个编程语言. 这个编程语言能做数学计算, 能作条件判断, 能 GOTO. 用现在的眼光看, 这个语言能构模拟图灵机上的一切操作, 所以是图灵完全的. 学过数值计算的同学都知道, 科学计算无非就是一大堆数学计算按照步骤进行而已. 所以, 一些控制判断语句, 数学公式加上一个数组, 基本上就能完成所有的科学计算了. IBM 觉得这个语言够用了, 就发布了 FORTRAN 语言规范, 并且在自家的大型机上实现了这个语言. 

在实现这个语言的时候, IBM 的工程师要写一个 FORTRAN 编译器 (请注意那时候的大型机没有操作系统). 那时候的编译器都是用机器语言或者很低级的汇编语言写成的, 所以编译器要越简单越好. 这些工程师觉得, 弄一个让用户运行时动态开辟内存的机制太麻烦了, 所以干脆, 强迫用户在写程序的时候, 就要定好数组的大小, 变量的类型和数目. 这个要求并不过分, 因为在科学计算中, 数组的维度, 用到的变量等, 在计算之前, 就是可以知道大小的. 用现在的话说, 就是不能动态开辟内存空间, 也就相当于没有 malloc 的 C, 或者没有 new 的 C++. 这样的好处是, 一个程序要多少内存, 编译的时候就知道的一清二楚了. 这个主意看上去很聪明, 不过 IBM 的工程师比你想得更加聪明, 他们想, 既然一个程序或者子程序要多少内存在编译的时候都知道了, 我们干脆就静态的把每个子程序在内存中的位置, 子程序中参数, 返回值和局部变量放的位置, 大小都定好, 不久更加整齐高效么. 是的, 我们都知道, 在没有操作系统管理的情况下, 程序的内存策略越简单越好, 如果内存放的整整齐齐的, 计算机的管理员就能够很好的管理机器的内存, 这样也是一件非常好的事情. (再次强调, 当年还没有操作系统呢, 操作系统要等到 1964年发布的 IBM 360 才有, 具体开发一个操作系统之难度可参考< 人月神话>).

可是, 聪明的读者一下子就看出来了, 这样静态的搞内存分配, 就递不成归不了了. 为啥呢. 试想, 我有个 Fib 函数, 用来计算第 N 个菲波拉契数. 这个函数输入一个整数, 返回一个整数, FORTRAN 编译器帮我把这个函数给静态分配了. 好, 我运行 Fib(5) 起来, FORTRAN 帮我把 5 存在某个专门给输入参数的位置. 我在 Fib(5) 里面递归的调用了Fib(4), FORTRAN 一看, 哈, 不还是 Fib 么, 参数是 4, 我存. 这一存, 新的参数4, 就把原来的 5 给覆盖掉了, 新的返回值, 也把原来的返回值给覆盖掉了. 大事不好了, 这么一搞, 新的调用的状态居然覆盖了老的调用, 这下, 就没法返回原来的 Fib(5) 了, 这样一搞, 怎么递归啊?

IBM 这些写编译器的老前辈们, 不是不知道这个问题, 而是压根就鄙视提出这个问题的人: 你丫科学计算递归什么呀, 通通给我展开成循环, 展不开是你数学没学好, 想用递归, 你就不要用 FORTRAN 了. 那时候 IBM 乃是老大, 只有他们家才生产大型机, 老大发话, 下面的消费者只能听他的.

既然软件不支持, 硬件也就可以偷工减料嘛, 所以, 硬件上, 就压根没有任何栈支持. 我们都知道, 计算机发展史上, 软件和硬件是相互作用的. 我们现在也很难猜测, 是IBM 的软件工程师因为 IBM 的硬件工程师没有在硬件上设计出堆栈所以没有能在 FORTRAN 里面设计出递归调用呢, 还是 IBM 的硬件工程师觉得既然软件没要求, 我就不设计了呢? 不管怎么样, 我们看到的是, 1960 年前, 所有的机器的硬件都没有直接支持栈的机制. 熟悉CPU的都知道, 现代 CPU 里面, 都有两个至关重要的地址寄存器, 一个叫做 PC, 用来标记下一条要执行的指令的位置, 还有一个就是栈顶指针 SP. 如果没有后者, 程序之间的调用就会非常麻烦, 因为需要程序员手工维护一个栈, 才能保证程序之间调用最后还能正确的返回. 而当年, 因为 FORTRAN 压根就不支持递归, 所以支持 FORTRAN 的硬件, 就省去了栈指针了. 如果一个程序员想要递归调用, 唯一的实现方法, 就是让程序员借用一个通用寄存器作为栈指针, 自己硬写一个栈, 而且不能用 FORTRAN.

因为 FORTRAN 不支持递归调用, 按照自然规律, 自然会有支持递归的语言在同时代出现. 于是, 很快的, LISP 和 ALGOL 这两个新语言就出道了. 我们只说 LISP. 它的创始人 John McCarchy 是 MIT 教授, 也是人工智能之父, 是学院派人物. 他喜欢丘齐的那一套 Lambda 演算, 而非图灵的机械构造. 所以, LISP 从一开始, 就支持递归的调用, 因为递归就是 lambda 演算的灵魂. 但是有两大问题摆在 McCarchy 面前. 一是他的 LISP 理论模型找不到一个可以跑的机器, 二是他的 LISP 模型中有一个叫做 eval 的指令, 可以把一个字符串当成指令在运行时求值, 而这个, 当时还没有人解决过. 按照 Paul Graham 大叔在他的 Hackers and Painters 里面的说法, McCarchy 甚至压根就不想实现这个 eval 指令, 因为当 IBM 的一个叫 Steve Russell的工程师宣称要实现 eval 的时候, McCarthy 还连连摇手说理论是理论, 实际是实际, 我不指望这个能被实现. 可是, Russell 居然就把这两个问题一并给解决了(这哥们也是电子游戏创始人, 史上第一个电子游戏就是他写的, 叫 Space War). 他的方法, 说来也简单, 就是写了一个解释器, 让 LISP 在这个解释器里面跑. 这个创举, 让传统上编译-> 运行 的高级语言流程, 变成了 编写-> 解释执行的流程, 也就是著名的 REPL 流程. 他做的事情, 相当于在IBM 的机器上用机器码写了一个通用图灵机, 用来解释所有的 LISP 指令. 这个创举, 就让 LISP 从理论走到了实践.

因为有了运行时的概念, LISP 想怎么递归, 就可以怎么递归, 只要运行时支持一个软件实现的栈就可以了. 上面我也说了, 也就是写解释器的人麻烦一点而已, 写LISP程序的人完全就可以不管下层怎么管理栈的了. 同时, 有了解释器, 也解放了原来动态分配空间的麻烦, 因为现在所有的空间分配都可以由解释器管理了, 所以, 运行时环境允许你动态的分配空间. 对空间分配的动态支持, 随之就带来了一项新技术: 垃圾收集器. 这个技术出现在 LISP 里面不是偶然的, 是解释器的自然要求和归宿. 在 FORTRAN 上本来被绕过的问题, 就在 LISP 里面用全新的方法被解决了. LISP 的划时代意义和解释器技术, 使得伴随的很多技术, 比如抽象语法树, 动态数据结构, 垃圾收集, 字节码等等, 都很早的出现在了 LISP 中, 加上 LISP 本身规则很少, 使用起来非常灵活, 所以, 每当有一项新技术出现, 特别是和解释器和运行时相关的一项新技术出现, 我们就会听到有人说, “这玩意儿 LISP 里早就有了”, 这话, 是有一定道理的.

除了上面的软件模拟之外, MIT 还有一派在作硬件模拟, 这一派, 以后发展成了灿烂一时的 LISP machine, 为日后所有虚拟机理论铺开了一条新路. 这一派在70, 80年代迅速崛起, 然后随着 PC 的兴起又迅速的陨落, 让人唏嘘不已.

最后附送一个八卦: 1960 年的时候, 高级语言编程领域也发生了一件大事, 即 ALGOL 60 的提出. ALGOL 是划时代的标准, 我们今天用的 C/Java 全是 ALGOL 家族的. ALGOL 注意到了 FORTRAN 的不支持递归的问题, 于是从一开始, 就订立标准支持递归. 但是, 处理递归需要很小心的安排每个函数每次调用的地址和所谓的活动窗口(Active Frame), 而并不是每个编译器都是牛人写的, 所以在处理递归这样一个新事物上, 难免会出点小问题和小 BUG. 这时候, 搞笑的高爷爷(Knuth) 出场了, 他提出了一个测试, 叫做 “是男人就得负67”. (The man or boy test). 恕我功底不深, 不能给各位读者把这个男人测试的关窍讲清楚, 但是, 我知道, 这个测试, 乃是看 ALGOL 60 编译器有没有正确的实现递归和外部引用的. 照高爷爷的说法, 真的男人要能得到正确答案, 不是男人的就得不到正确答案. 当然, 高爷爷当时自己也没有男人编译器, 所以自己猜了一个 -121, 后来, 真的男人编译器出来了, 正确答案是 -67. 可见, 高爷爷的人脑编译器, 也不是男人编译器…

各位欲知详情的, 猛点这个.

May 10, 2009 - 论动鸡不良

Comments

我不认识周曙光, 没见过面, 只在网上说过几句和计算机有关的话. 但是看看他做的事情, 就知道他是个有趣的人. 每次热点事件, 周曙光不是亲自去现场, 就是立即做专题. 上次的俯卧撑, 山寨牛博, CCAV 事件等等, 我基本上都是直接看周曙光的聚合信息. 他是一个善于利用传播方法的人.

每次, 总有人出来怀疑周曙光的动机. 我不知道这些人是什么样的心理. 李笑来老师在博客上维权的时候, 有一个人就说, “你这样跟网络暴民有什么区别,得理不饶人啊.人家都联系你了,你不理人家,那么你的目的到底是要退款还是把事情搞大.” 这次周曙光做了一个70码的专题, 又有人说, “不知道那些所谓公民记者,是对 杭州事件 极其感兴趣亦或为了伸张正义? 一直抓住不放。四川出现H1N1疑似咋不去追踪、报道?甚至怀疑政府别有用心囧。我感觉他们是在借 #70km 事件炒作自己。制作网站http://70km.org/ 并租售广告位,可见一斑。” 还有包括周曙光去 Google 维权, 也有一大帮子人不从事情本身角度来思考, 却口口声声说周曙光又炒作了.

在这些人眼里, 别人做事, 不管事情本来的原因是什么, 做的人一定要声张正义, 一定要不牵扯任何的个人利益, 一定要在他眼里公平公正, 这个事情才能做, 才做得对, 否则就一定是别有用心炒作自己. 这个思维方式, 不客气的说是被高大全英雄主义和顺民逻辑洗脑后的结果. 在这些评论者的眼里, 一个人一定要清纯的像水晶一样, 才能够做专题, 才能写博客, 否则, 就是要把事情搞大, 就是别有用心. 在他们的社会里面, 一定要大事化小, 小事化了才是正常的逻辑; 若非如此, 就一定是炒作自己. 多年网上论战经验表明, 和这些脑子被门夹了的人说清楚一个道理很难, 特别是不接受逻辑还口口声声号称正义的人, 是无法用正常人的逻辑说服的, 所以, 我也就懒得写文字一一反驳这些话语了.

我是希望更多的人像周曙光老师这样, 把越来越多的事情”好玩化”, 用轻松愉快又赚钱又不摸老虎臀部的方法, 把个人利益和社会责任结合起来, 既能让大家得到信息, 又能在这个过程中获得个人利益的诉求的满足. 这样轻松愉快(其实我知道, 在贵国, 这可不轻松愉快, 但现有的阶段, 只能这么做, 原因可参考我以前文章. 周曙光老师和连岳老师, 冉云飞老师, 以及韩寒老师一样, 都是底线守得非常好的实干家) 又双赢的事情, 都是聪明人才能做得到的. 把事情做到双赢局面, 其实不是人人能做到的. 很多嘴上牛逼哄哄, 天天说你说他的的评论家, 大都抵不上前面四位老师的机灵劲儿的.

周曙光老师这样的人, 是典型的王小波笔下的”有趣”的人. 这样有趣的人, 要越多越好, 这样社会才能有趣, 未来才能有趣. 再说, 动鸡这东西, 本来就是正常人的需求嘛. 鸡这个东西, 长在人身上, 本来就是用来动的嘛. 部分观众偏要指责动鸡不良, 也太摧残人家周曙光老师的人性了吧.

May 10, 2009 - To boldly go where no man has gone before

Comments

Star Trek 是个很有文化的美剧, 巨喜欢这句:

Space… the Final Frontier, these are the voyages of the starship Enterprise. Its five-year mission: to explore strange new worlds, to seek out new life and new civilizations, to boldly go where no man has gone before.

后一句翻译过来是

探索未知的新世界, 寻找新的生命和新的文明, 勇敢的去前人从未到过的地方.

来美国之后, 我逐渐知道了 Star Trek 这个系列的美剧, 知道了 USS-Enterprise 的探险故事, 知道了 Captain Kirk, 知道了克林贡语. 这个剧集实在是 geek 必看啊! 这次的电影也巨酷, 我是周五晚看的IMAX, 太赞了. 我就不剧透了, 总之, 任何理科男都必看, 文科小资男小资女等想了解腐朽资本主义国家落后文化的, 必看.

To boldly go where no man has gone before!

May 8, 2009 - 美国公民自由联盟的那些著名官司-5

Comments

第四修正案和跨州追捕

美国宪法第四修正案, 也就是权利法案第四条, 原文是:

The right of the people to be secure in their persons, houses, papers, and effects, against unreasonable searches and seizures, shall not be violated, and no Warrants shall issue, but upon probable cause, supported by Oath or affirmation, and particularly describing the place to be searched, and the persons or things to be seized.

翻译成中文是:

人人具有保障人身、住所、文件及财物的安全,不受无理之搜索和拘捕的权利;此项权利,不得侵犯;除非有可成立的理由,加上宣誓或誓愿保证,并具体指明必须搜索的地点,必须拘捕的人,或必须扣押的物品,否则一概不得颁发搜捕状。(http://usinfo.org/zhcn/GB/PUBS/LivingDoc/billrights.htm)

很显然, 聪明人一眼看出来这一条, 就是限制公权对人民权利的毫无理由的迫害. 特别的, 作为执法机关的警察, 若无司法机关颁发的许可令(行政机关无权颁发搜捕令), 是不得随便拘捕公民的. 并且, 搜捕状上, 具体写清楚了警察可以做的事情和可以抓的人. 通常, 搜捕状是一个州内有效的, 州之间一般不互相承认搜捕状. 所以, 一个州的警察, 即使有搜捕状, 也没有任何权利到其他州去抓人, 除非这个警察是联邦政府的警察, 带有联邦法院的搜捕令. 喜欢美剧 24 的朋友们都知道, 杰克-鲍尔 常常对着 FBI 的上司大喊大叫要搜捕状, 否则去搜查恐怖分子也是非法的. 电视剧里面, 往往都是杰克很聪明, 上司很混蛋, 往往不给搜捕状. 所以鲍尔先生就违反规则老自己瞎搞, 结果搞到最后, 把自己搞到国会听证席上去了, 被一群参议员狂问问题.

那么, 就不能跨州追捕了? 不完全是, 警察照样可以开着车在高速公路上跨州”追”, 但是已经没有权利去”捕”这个罪犯了, 只能委托当地警察. 如果被抓住了, 警察也不能把他押回, 而是要当地警察, 甚至是当地法院处理这个事情, 而跨州的那些警察只能把这个人犯罪的证据交给当地警察处理.

总之, 按照美国法律的规定, 地方政府想要跨州追捕, 这事情基本上是没什么希望的. 这个情况就造成了一些好玩的结果. 第一就是”随法律迁徙”. 一个州里面非法的事情, 到另外一个州就不非法了. 所以, 想结婚的同性恋就换个州把婚结了, 让原来州的那些反对同性恋的地方官员吹胡子瞪眼; 或者, 在废除奴隶战争前, 在南方逃脱的奴隶其实按照南方州法律是有罪的, 他们逃到北方, 南方的警察也不能跨州追捕, 就眼睁睁看人家在北方成为了自由人; 或者, 美剧里面常常有对话说, “你这鸟样, 搬到东西海岸去”, 这就是说, 中部保守州不认同某些行为, 而东西海岸比较自由, 所以喜欢自由的人都往东西海岸迁徙. 这些美国历史上发生的事情和流行文化里面的现象, 都是因为第四修正案的保护和适用范围界定, 才显得可能.

但是这世界上, 有一种犯罪, 是恶疾难除的, 还非要跨州追捕不可. 这就是所谓的 hate crime (仇恨罪). Hate Crime, 就是基于宗教, 文化背景, 种族, 价值观, 性取向, 政治观点, 所属政党等为正确与否的判断依据, 恶意攻击和侵害实践不同观点的人的犯罪. 这里面, 常常听说的就是天主教徒持枪血洗流产诊所(天主教反对堕胎), 白人精英主义者歧视和欺负有色族裔等. 虽然美国一直在推动社会的宽容, 用严厉的手段打击这些歧视和不公平, 但是不宽容的人和事情总是存在的. 所以要不断的立法限制这种 Hate Crime.

基本上世界上所有发达的文明国家都有针对这种犯罪行为的立法. 在美国, ACLU 也一直在推动美国在 Hate Crime 上更加严格的打击力度. 但这个问题很纠结也很难辩论清楚, 原因在于对不同观点的恶意攻击, 特别是轻度的言语和行为骚扰, 既可以牵强的认为是实践言论自由, 也可以理解为是犯了 Hate Crime. 怎么界定基于 Hate 的犯罪是一个很大的问题. 加上不同的州, 观点和法律不一样, 在一个州的犯罪到另一个州就变得合法, 这样, 即使犯罪了, 也不能跨州拘捕, 就造成了不同的州对 Hate Crime 的界定不一样. 这时候, 就需要联邦政府的协调.

最近, 乘着民主党控制参众两院的机会, 国会众议院已经通过了一个叫做 H.R. 1913 的法令, 旨在让联邦政府帮助地方政府, 惩罚 Hate Crime. 因为联邦政府有跨州追捕的权利, 也有足够的资金来支持地方对 Hate Crime 的调查和宣判. 照现在的民主党控制国会的样子看, 这个法律是肯定会通过的. 到时候, 犯 Hate Crime 的不宽容的分子, 就会迎来地方政府委托联邦政府 FBI 跨州抓捕的特殊待遇了.

归根到底, 这些法律, 都是用来保护弱势群体的. 历史证明, 如果没有法律和正义, 而是靠一时包青天, 弱势群体随便怎样都得不到长效的, 持久的保护. 试想, 如果有人敢在大街上叫我”小黄人, 滚回亚洲去” 这种话(当然从来没有过), 我想到的, 不是告诉他我们”小黄人”也有原子弹, 以便让他很害怕; 而是合法声张自己的权利, 告死丫挺的. 在一个有法律的国家, 如果遇到歧视就比家里有没有XY蛋, 这心态就和小孩子比谁鸡鸡大尿的远一样. 似乎鸡鸡大了, 就可以不受歧视了, 或者就可以歧视鸡鸡小的了. 用弗洛伊德的话说, 这是典型的 Penis Envy (http://en.wikipedia.org/wiki/Penis_envy ). 其实小时候的经验就告诉我们, 随你是不是当年迎风尿八仗, 等你顺风尿湿鞋的时候, 还是免不了被歧视. 实践中最好的方法, 不是比鸡鸡大, 而是能建立一个不需要比鸡鸡大也能相互尊重的公正体系, 而这样的体系, 就是要靠这些立法来一步一步建立.

May 4, 2009 - 也说庄家赢钱的奥秘

Comments

松鼠会最近有篇文章, 叫做从庄家不输钱谈起, 用概率论的知识解释了庄家为什么不输钱. 作者的解释是和庄家玩, 庄家的数学期望总是正的, 赌钱的人的数学期望总是负的, 所以总是庄家赚钱. 其实这个解释是不准确的.

如果赌博仅仅是一个人和一个庄家之间的零和博弈的话(你的赢就是庄家的输, 反之一样), 那么, 去赌钱的人, 就没有所谓的技术差异了, 反正都是死. 事实上, 赌博, 比如赌球, 赌扑克这些, 高手和新手差距是很大的. 这也就是说, 如果我们把赌博看成是庄家和玩家之间的概率游戏的话, 高手和新手的获胜概率还不大一样, 这样, 用数学期望就解释不通了, 因为庄家在不出老千的情况下, 是没法让高手的数学期望为负数的, 这样, 庄家只对新手有正的数学期望, 而这个, 是和我们观察矛盾的, 庄家其实不管你来赌钱的是谁都是赢钱的, 这是和赌博的人是不是高手一点关系没有的.

要解释这个现象, 最核心的是要承认一点: 庄家其实不是直接和玩家赌钱的. 庄家乃是让玩家之间赌钱, 自己通过巧妙的方法赚钱. 我简要介绍这些方法中非常巧妙的, 也是和金融息息相关的一个手段, 叫做对冲.

我们以赌马为例. 假设有两匹马 A 和 B, 第一匹马赢得概率是 0.6, 第二匹是 0.4, 有两个赌徒, 第一个买A赢, 第二个买B赢, 来说, 两人如果不带庄家面对面各自下注的话, 假设第一个人出 x 元, 第二个人出 y 元(单位都是美元, 下同). 则第一个人赢的钱的期望是 0.6*y – 0.4*x, 第二个是 0.4*x – 0.6y. 很自然的, 如果要游戏公平的话, 两个人中, x 应该取 60, y 取 40. 这样, 两个人赢钱的数学期望都是 0, 这是对两个人都公平的游戏.

这时候, 庄家出现了, 这两个人, 现在都向庄家买马. 庄家想要赚钱, 最重要的一条就是旱涝保收. 所谓的旱涝保收, 就是说, 不管A, B 两匹马怎么跑, 庄家总能赚钱. 怎么做呢, 这就是庄家牛B 的地方了.

我们假设A 马和 B 马上, 各自共有 100 块钱 和 200块钱的赌注. 那么, 庄家一共收到了 300 块钱的赌注.  自然的, 庄家想自己抽水2成, 剩下的 240 块钱作为奖金回报给赌徒. 如果 A 赢了, 对于买 A 马赢了的人, 庄家就给你240块. 同样, 买B的也一样. 请注意, 这时候, 庄家不关心 A 还是 B 赢的概率的, 这就是关键.

那么, 为什么有人赌呢, 因为对于投 A 赢的人来说, A 赢了, 他能赢 140 块钱; 对于 B 来说, B 赢了, 他能得到 40 块钱. 那么, 对于投 A 的来说, 只要在他心目中, A 赢的概率超过 5/12, 他就愿意赌博 (他得到的钱的期望是  0 + 5/12 * 240 = 100 = 他的投资), 因为他赢钱的数学期望超过他的投资了.  对于下注到 B 的赌徒也是, 在他们心目中, 只要 B 赢的概率超过 10/12 了, 他就愿意了 (期望 = 0 + 10/12 * 240 = 200).  庄家定出的这个回报, 对于买 A, 就是投 100 最后还返还 140, 所以有叫做 1 赔 1.4; 同样, 对于 B, 叫做 1 赔 0.4. 这就是赔率的通俗定义.

可以看到, 庄家加入之前, 两个人赌钱的时候, 一匹马能赢的概率, 是一个变量, 这个量, 由两个玩家之间的协商. 而庄家来了之后,  一匹马能不能赢, 就看赔率. 不同的赔率其实对应了不同的概率. 至于您相信哪种概率, 就是你自己的事情了.  所以, 你完全不觉得自己的数学期望是小于0的. 事实上, 你总认为你猜的概率是真实的概率, 继而相信自己下注的数学期望大于0, 这时候,  您才会去充满自信的赌球的.

可是上面说的这些, 需要一个前提, 就是庄家知道投A 和投B 的人的比例. 否则的话, 庄家就有可能赔钱. 比方说, 庄家开出了 A 1 赔 1.4, 结果来了一个大玩家, 一下子买了1000美元的 A. 这时候, 赌资总共是 1300 美元. 这 1300 美元, 庄家可就不一定稳赚了, 因为假如 A 赢了, A 上的赌资一共是 1100 美元, 庄家就要赔 1100*1.4  > 1540 美元. 而庄家一共才收了 1300 美元的赌资.

庄家是资本家, 不是赌马专家, 他不会仔细研究 A 赢的概率(其实也会, 但是不会依赖于这个概率, 我下面有讲), 看看自己以多大的概率输掉这个 1540 美元, 而是立即采取补救措施, 消解自己的风险, 这个风险消解, 就叫做对冲. 没错, 就是对冲基金的那个对冲.

一般来说, 庄家有两种做法. 第一种是调整赔率法. 庄家赔钱的本质, 是因为 B 上现在没有足够的赌注, 来补偿 A 上的赔率. 那么, 庄家就调整 A 的赔率, 让 A 赔的少一点, B 多一点. 这样, 这个杠杆就会向 B 倾斜. (对于已经买了的, 赔率照旧, 这个只对新的玩家有效). 这样, 庄家就能利用这个杠杆, 让自己的风险得到对冲. 庄家也能拒绝那个买 1000 美元 A 的大玩家, 这样让整个赌注的比例得到控制.  但是这些方法不能搞太多的, 因为一个博彩公司老是调节赔率, 或者老是拒绝客户, 这个博彩公司就离倒台不远了.

所以, 博彩公司采用另外一种方法: 自己也买. 比如, 博彩公司知道 A 上面赌注太多了, 赔率又太高, 一旦 A 赢了, 自己要把内裤的输掉的, 所以, 他也跑到市场上, 找到另外一下博彩公司, 也买A. 一般来说, 博彩公司之间的赔率相差不大. 这样, 就算 A 赢了, 博彩公司也不怕, 因为他可以从别人博彩公司赚一笔, 对冲掉自己为了 A 要付出的风险.

正是因为博彩公司采用了其实更加复杂的赔率的计算方法和巧妙的对冲方法, 才能保证赚钱. 不过, 要搞这两个, 一要有很多现金随时调动, 二要很准确的初始赔率的设置(需要赌马专家和数学家一起估计), 所以, 在美剧里面, 不是大资本家和数学家在搞, 就是犯罪分子绑架数学家在搞.

总之, 庄家赢钱, 不是简单的数学期望结果, 而是复杂的赔率方法和巧妙的对冲操作的结果.