终于知道计算器上的 % 键有什么用了

2012-02-17 – 19:55:39

就是最最最最普通的那种计算器。科学计算器不是这样的。

我从小时候第一次摸到计算器就很困惑这个 % 键是干什么的,因为貌似你不管输入什么数字,按一下 % 数字就会变成 0. 有的时候在计算过程中误按到 % 键,屏幕上会突然冒出来一个无比奇怪的数字,只好从头重来。

直到今天看到了 Raymond Chen 大神的一篇文章才恍然大悟。原来这个键是以一种理科生无法理解但是对普通人很自然 (hopefully) 的方式运行的。比如你输入 700 + 5% =,那么结果“自然”是 735,而不是 700.05。同样的,输入 1000 – 8% =,结果“自然”是 920,而不是 999.92。

我说的“自然”是说,当你心想“700加上百分之五是多少”的时候,你预期的结果是 735。如果你想计算比如“500的5%是多少”这样的问题,对不起,不是 500 × 5% =,因为那样算出来的是“500乘以500的5%”。不过你可以不按等号,这样虽然比较 hacky 但是也可以达到你的效果。

这功能其实挺实用也挺强大的,比如商店打 8 折,折后加 9.5% 的税,那么你就可以计算 12.34 – 20% + 9.5%. 可惜 iPhone 上的计算器没有提供这个功能。

好吧,其实提供了我也不会自然的列出那个算式,还是要想半天⋯⋯

 


SQL Server: 如何在 CLR Trigger 里面 Rollback Transaction

2011-11-10 – 13:46:26

MSDN

在 Trigger 里边调用 Transaction.Rollback(),或者执行命令 ”TRANSACTION ROLLBACK”,你会得到一个异常说你不能在 CLR trigger 里面 rollback transaction. 不要管他,用 try/catch 把这个异常吞掉,然后继续该干嘛干嘛。Trigger 执行结束之后你还会得到一个异常说本来好好的 transaction 怎么被你的 trigger 终止了,你的程序有问题。还不要管他,用 try/catch 把这个异常吞掉,然后继续该干嘛干嘛。最后反正你还是达到了 rollback transaction 的目的。

佩服死了..


美国个人银行服务与中国之对比

2011-07-22 – 00:17:26

在美国居住半年有余,趁着还没忘记国内银行服务的状况,把我观察到的一些有意思的现象列举出来。

1. 支票

支票作为一种很“落后”的支付手段,至今仍然在美国起着相当重要的作用。虽然人们已经不常在商店使用支票付款,但在某些情况下,支票仍有其不可替代的优势:

  • 个人之间的付款。现金需要找零;银行转账、PayPal 等都需要知道对方的账号,且不能离线交易(例如付款给出租车司机)。
  • 公共事业账单、房租、信用卡还款等。大部分情况可以在线搞定,但仍有一些公司不提供在线支付业务,这个时候支票的优势就体现出来了——可以邮寄,支付时不需要对方在场。
  • 企业给个人的付款。例如某些商家有返现优惠(cashback),这个时候商家就会寄支票出来,因为你总不能把银行账户信息随便给商家吧。发工资的情况比较复杂:你可以给公司提供银行账户信息,让公司直接把工资存到银行里(叫做 direct deposit),而如果不这么做,“默认”的支付方式是支票 (paycheck)。
  • 其他:例如我每次充公司饭卡都会写张支票,因为食堂不收信用卡,我也懒得到处找 ATM 去取现。

支票怎么兑换成现金呢?可以去银行把支票“存”在账户里,在美国这是银行提供的最最基础的服务之一,就像在国内存取现金一样。你可以在柜台存,也可以在自助机器存,可以下班时间把支票扔到 “night deposit box” 里银行第二天会处理,甚至可以直接寄给银行。现在 Chase 银行还可以用 iPhone 客户端给支票照张相,直接电子兑换。兑换过程大概一两个工作日。

国内的情况:不用说大家也知道,个人支票是玩不转的。国内没有支票的等价物,人们通常使用现金进行上述活动。

2. 银行账户

美国的银行有两种最基本的账户:支票账户 (checking account) 和储蓄账户 (savings account)。这两种都类似国内的活期账户,但不太一样。支票账户,顾名思义,就是存取支票用的账户,相当于国内说的“结算账户”,用于结算。上面已经说过,存取支票是最最基础的服务之一,因此支票账户是个人账户中最最基础的一个。现金存取一般也通过支票账户来进行。而储蓄账户则是一个用于活期储蓄的账户。区别在于,支票账户一般没有利息或只有很低的利息;储蓄账户的利息高一些,但是每月有存取次数限制,例如取现超过 4 次就要收费。

在美国银行账户不一定关联到一张卡或一个存折。去银行开户一般会得到一个支票本,和一些合约什么的,也就是说这个账户并没有一个实体的凭证。下次去银行办业务的时候,带上驾照就可以,柜员会通过名字和地址找到你的账号。怎么知道交易详情呢?银行会每月寄出账单,上面列有这个月所有的交易和账户的余额。月中怎么办?在没有网银的年代,美国人需要人肉记下账户所有的进出情况。每个支票本里边都有一些记账条,你每写一张支票(出),或者兑换一张支票(入),都需要更新这个记账条,然后算出自己的余额,所谓 balance your checkbook. 当然有了网银就不需要做这些事情。

国内的存折很像这种记账条,不过是由银行管理的。美国貌似没有存折这种东西。银行账户是没有密码的,全凭识别身份。

3. 转账

美国的银行间结算系统很统一:每家银行都有一个 9 位的 Routing Number,以及每个账户都有一个账户号码,这样用这两个号码就可以确定美国国内的任何一个银行账户了。不像中国有无数种清算系统,并且不是所有银行都接入这些系统。这样就使得美国上万家银行的账户都可以用统一的方案相互交易。在美国一个人在不同银行持有多个账户是很正常的,并且这些账户之间互相转账是免费的。只有转账给别人的时候才可能会收费。你可以从 A 银行把钱转给自己在 B 银行的账户,也可以从 B 银行直接扣 A 银行账户的钱,都是通过上述的两个号码。另外美国没有异地的概念,只有国内和国际的区别。

因为银行账户是没有密码的,所以账户号是敏感信息,一般别人也不会给你。所以从银行转账给别人并不是一个常用的功能,这种需求都由支票解决了。在美国,银行账户是可以做网络交易的,也就是说你在一个商家填了 Routing Number 和账户号码,这个商家就可以扣你的钱或者给你钱。注意,没有密码。我的房租就是这么交的,每月房东直接从我银行账户里边扣钱,刚开始不习惯,时间长了就淡定了⋯⋯

这个系统唯一的缺点,就是转账太慢,只要是跨行转账,怎么也要两个工作日才能完成。

4. 借记卡和信用卡

进入 21 世纪,就需要借记卡了⋯⋯ 毕竟在可以用卡的情况下,用卡还是比用支票方便快捷很多。在银行开户的时候可以要一张借记卡,但是借记卡一般来说不是当时就能给你的,而是需要经过若干工作日邮寄到家,再经过若干工作日会收到一张密码条,然后电话激活就可以用了。借记卡有 4 位密码,用 ATM 取钱时需要输密码。以前的借记卡 (debit card) 是不能当信用卡刷的,但是现在的借记卡又叫 check card,这种卡在商店刷卡时可以用密码也可以不用密码,当信用卡刷。在网上交易时无法输入密码,和信用卡一样凭卡号、有效期等信息即可交易。当然,被盗刷的话给银行打个电话,银行会妥善处理的。

还有一个很大的不同,就是国内借记卡的结算都是实时的——不管你是在商家消费,还是给别人转账,还是存钱,借记卡里的钱是多少就是多少,进出都是实时的。而美国的结算会有延迟。你从商家刷了卡,当时可能会出现一条 Pending 的交易,过两天才会像信用卡一样正式入账。因此美国的银行账户都有两个余额:一个正式余额,一个可用余额。甚至可能出现商家过两天才扣款的情况。这种情况如果金额不大,银行是可以把你的余额扣为负数然后再向你追讨欠款的。

美国的信用卡和国内的还是差不多的。区别在于优惠比中国的多一些。例如我有一张卡利率 6.25%,最低还款额 2%,远远低于国内的 18.25% 和 10%。有两张卡会对任何消费返还 1% 的现金,远远高于国内的积分计划。还有一张卡第一年是完全免息的。不过正是由于这些利好,使得美国人民很容易欠下太多的债务而无力偿还。由于近年来借记卡都可以当信用卡刷了,美国人越来越流行使用借记卡消费,以控制购物欲望。在美国可以没有信用卡,但是如果没有借记卡的话就会很不方便。

5. 现金和 ATM

现金是一个很少很少被用到的东西。一般来说除了某些华人商店会不收信用卡之外,所有商店都会收信用卡;所以美国人一般不携带现金或者只携带很少的现金。用现金的以青少年和非法移民居多。ATM 很多,但是一般跨行取款都需要交两份钱:发卡行一份,ATM 归属行一份。有些银行可以免第一份,还有些更好的银行不仅免第一份还会报销第二份。例如 Ally 银行,是一家没有实体店的银行,所有业务都通过网络、电话和邮寄来完成。因此它可以把成本控制的很低,来给客户提供尽可能高的回报。我就用这家银行的 checking account 作为我的主账户。他家没自己的 ATM,但你可以免费的使用任何一个别家的 ATM。

总之,现金是一个几乎已经退出历史舞台的东西。中国在这方面和美国差距太大了。

6. 其他

我觉得美国人民到中国的银行营业厅里一定会被吓到的。在美国的营业厅里,只有冷冷清清几个人,柜台是开放式的没有玻璃隔离和对讲机,排队也是古典方式没有叫号系统。开户什么的要去跟 banker 一对一的坐下面谈,而不是直接在柜台办理。这其实也反映了以支票业务为基础的特点——毕竟不需要服务大量的现金存取款业务,也不需要用特别的安全措施来保护大量的现金。很多银行网店还有 drive-thru 窗口,开车开到窗口人不用出来就可以办理业务,真是一个适合懒人的东西。

总之,美国的银行系统和中国的非常不一样,所以刚来的时候会很糊涂。美国以支票为基础,中国以现金为基础;美国银行转账方便,但速度慢;美国银行默认所有人都是守信的,中国银行则从技术上追求实时结算。两种不同文化环境下规则迥异的系统都能正常工作,且都适合当地人民的习惯,这还是一件很神奇的事情。


数学扫盲之 e 是什么

2011-07-12 – 23:41:10

【谨以此文吐槽 An Intuitive Guide To Exponential Functions & e 及其译文。】

【写了一半发现白写了,请参阅《自然對數漫談》,原载于《數學傳播》23卷1期,作者宋秉信。】


SQL Server: 不要把 binary 和其他类型互相转换,尤其是 numeric/decimal

2011-06-30 – 12:37:43

昨天在 stack overflow 上看到一个有趣的问题,这倒霉孩子把 binary(8) 转换成 numeric 之后,再往回转就乱套了。经过一番徒劳的解释,这孩子还是认定这是个 SQL Server 的 bug, 从 6.0 到 Denali 一直没有修好。

其实不是这么回事儿。在 SQL Server 里把一种数据类型转换成 binary,得到的是该类型的内存表示,就像 reinterpret_cast 一样。比如你把一个浮点数 1.0 转换成 binary(8),你不会得到 0x01,而是 0x3FF0000000000000. 相反也是一样,SQL Server 保证你把足够长度的 binary 转换回原来的类型,如果版本不变的话,还会得到原来的值。也就是说你把 0x3FF0000000000000 转换成 float 类型,得到的还是 1.0.

这倒霉孩子做了什么呢,他把 binary(8) 的数据转换成 numeric(20, 0),企图把它变成等价的整数。问题是,numeric 是个很变态的类型,它的内存表示是比较复杂的,而且每个版本都不太一样。比如以下脚本

declare @var numeric(20, 0) = 0;
select convert(binary(8), @var);

你可能期待 0x0000000000000000,但是得到一个类似 0x1400000100000000 的奇怪玩意儿。那么把 0x0000000000000000 转换成 numeric(20, 0) 会得到什么?

答案是,转换错误。

其实这并不是一个 bug,而是 0x0000000000000000 并不是一个合法的 numeric(20, 0) 对象。虽然 MSDN 说你可以把 A 类型转换成 B 类型,但并不代表 A 类型的所有值都能转换成 B 类型,不然你把 10000 转换成 tinyint 试试。所以其实这不是一个 bug,只是超出了值域而已。

然后这倒霉孩子的 workaround 是什么呢,他把 binary 的值上面加了个 0,然后再转成 numeric,然后幸福的发现工作正常了。binary + 0 会发生什么?根据 Data Type Precedence,binary 类型会被提升到 int,然后再加 0,然后再做 int 到 numeric 的转换。这样当然就得到该 binary 类型对应的数值了。但是他往回转的时候,直接做了 numeric 到 binary 的转换,于是得到了一个奇怪的数值。例如:

declare @myBinary binary(8) = 0x00;
-- binary -> int -> numeric
declare @myNumeric numeric(20, 0) = convert(numeric(20, 0), @myBinary + 0);
-- numeric -> binary
select @myBinary, @myNumeric, CONVERT(binary(8), @myNumeric);
-- Result: 0x0000000000000000, 0, 0x1400000100000000

看到问题了么,往回的时候不是原路返回的,所以出错了。如果先把 myNumeric 转成 int,再回到 binary,就不会出问题——至少在这个例子里。问题是 int 是 32 位的,装不下 binary(8),所以如果要装下的话得用 bigint。而原帖中的倒霉孩子之所以用 numeric(20, 0),是因为对足够大的 binary(8),转成 bigint 会出现负数,而这会对他在应用层中排序造成困扰。对于这种情况,最好的办法是不要做转换,直接在应用程序中处理二进制数据,以免发生意想不到的情况。


一号航班

2011-06-20 – 21:45:15

突然很好奇各大航空公司的 1 号航班都是从哪里到哪里的。随便查了几个 (6月20日数据):

Continental: IAH-HNL-GUM
没想到,居然是关岛航班

United: EWR-LAS (Codeshare CO268)
这个。。。

American: JFK-LAX
说得过去

US Airways: PHX-ORD
US 的航班号老改,不过这个也说得过去

Delta: LAX-JFK-LHR
总算出现纽约-伦敦航线了

Singapore: SFO-HKG-SIN
相当靠谱

Cathay Pacific: HKG-DXB-MAN-BRU
好多段啊。。。

ANA: IAD-NRT
首都航线

国内就不用找了,就没有小于三位数的


Windows 7 安装技巧两则

2011-04-02 – 06:41:30

一是,Windows 7 可以安装在硬盘上的一个 .vhd 文件里,这样的好处是装新系统不需要重新分区,不需要影响已有系统,可以跟虚拟机一样把硬盘镜像拷来拷去,还是确实运行在真的硬件上的。据说性能损失只有 3%.

步骤:(Ref: http://blogs.msdn.com/b/knom/archive/2009/04/07/windows-7-vhd-boot-setup-guideline.aspx)

进入安装程序后,按 Shift+F10,然后找到一个适合放镜像的分区。我原来系统的 C 盘在安装程序里变成了 D 盘,所以我可以输入:(橙色是我输入的部分)

X:\Windows\System32> diskpart
DISKPART> create vdisk file="D:\secondary.vhd" type=expandable maximum=80000
DISKPART> select vdisk file="D:\secondary.vhd"
DISKPART> attach vdisk

这样就建立了一个 80GB 的虚拟磁盘,然后就可以正常安装 Windows 了,它会提示不支持安装到这个盘,不用管

二是,Windows 把所有驱动程序都放了一份在 C:\Windows\System32\DriverStore\FileRepository 下面,只要先在设备管理器里找到要加载的设备的名字,然后去这个目录下一搜就能找到 INF 什么的,如下图。

这些文件直接拷出来就可以作为驱动的备份,如果重装之后找不到驱动了,可以直接装这个。另外,如果从网络安装的时候没有网卡驱动,也可以这么加载

X:\Windows\System32> cd D:\Windows\System32\DriverStore\FileRepository\net...2211
D:\...> drvload netb57va.inf
D:\...> netcfg -WINPE

然后 ipconfig /all 看一下,没问题,继续就行了!


编号的本子

2011-03-07 – 13:57:46

小时候一直不理解为什么有的人喜欢收集东西,尤其不理解集邮的,因为邮票不像钱币一样一共就那么几种,邮局经常闲的没事就印一套,那你是永远都收集不完的。小时候还曾经动过收藏汽车票地铁票公园门票的念头,但是也没执行过。

后来上了中学上了大学,开始对本子产生浓厚的兴趣,经常买来一些看起来挺好看的本子然后囤起来舍不得用。最发指的一次,大一刚开学时在超市看到有一套本子上边有1-8的编号,而且是8种不同颜色,于是毫不犹豫的翻箱倒柜的把8本都找了出来然后各买了一本。到现在可能只用了一小部分,不过仍然最喜欢这一套。后来就一发不可收拾的加入了本子控的行列。当然,这不能算收集,因为还没强迫症到所有见过的都入手一份。不过这种有编号的东西使我开始有点感觉到强迫症的意味了——毕竟只买一个子集总觉得少了点什么。

后来有了信用卡,发现各种花花绿绿的卡面也很有意思。然后招行的现存客户又可以随便申请新的卡片,于是我就把我喜欢的样式几乎全都申下来了——当然,白金卡无限卡是我最喜欢的,但是那个搞不定。(当然,借记卡攒起来比信用卡容易多了,但是卡片往往没那么好看。)这一堆卡片刚开始的时候给我带来了很多乐趣,但是后来乐趣消退之后,发现管理它们还是挺麻烦的,毕竟要记得每卡每年刷够N次,不然要交年费的。最近就湿鞋了一次,给招行股东们——虽然我也算其中一个——贡献了150大元。

图为我的银行卡收藏。虽然跟网上的卡神们没法比,但这些对我来说已经很有成就感了。

再到后来开始出国旅行,然后回国之前总要在机场尽最大可能把外币用掉,或者回来之后立即去银行兑掉。后来看到有同学会收集外币,就觉得出国一次没留下点东西也挺遗憾的,后来就把见过的各种货币都收集一张/一枚。幸好我只收集见过的,还没蛋疼到要收集所有发行过的货币,不然这张10000新元的纸币就直接让我破产了。这个收藏规则到美国之后就突然变得困难起来,因为美国的硬币实在是太适合收集又难收集了——每个州都有一个quarter纪念币,每个总统都有一个$1纪念币(虽然还没发行完)——这就是几十种不同的硬币,还不算其他乱七八糟的种类。至今我只收集了27个州,5个总统的纪念币。现在每次用现金购物的时候,总会把找回来的零钱过滤一遍,有纪念币留下,其他的花掉。

后来发现美国人简直是在故意调戏我们这些有收集癖的人,就像我开头说的邮局闲的没事印东西一样——他们还有各州州旗系列纪念邮票(1 2 3 4),各种景点的Pressed Pennies,等等等等。这些东西都是成套的,就像有编号的本子一样,让人总想“集齐”一套东西,虽然没有奖,但是很有成就感——或者是集不齐就会有失落感。昨天看到州旗系列邮票的时候,我就顿时明白为什么人们会集邮了——因为这种收集癖是没法抑制的。好在当供应大到一定数量的时候,这种收集的欲望就会自然的消散掉,毕竟自己没有实力一下子把那么多东西都买下来。但是当供应很少或者东西很便宜的时候——例如quarter和邮票——这样的欲望就会让人心里痒痒的。让我不明白的是,央行铸造硬币是希望它们能流通,可是人们都把它们收集起来了,流通不就少了么?

哦对,我还攒了09年到现在的所有登机牌。


如果汽车有Event Log

2010-11-23 – 21:24:44

昨天开车出了一点小事故,路滑刹不住车跟前车追尾了,好在双方人车都没事。不过事后作为软件民工我的第一反应居然是去查车的日志来分析到底是出了什么问题,然后才反应过来车子没有日志……

想象一下,如果给车子加个日志系统,这逻辑还是很清晰的,有 Information(一切正常的信号),有 Warning(仪表盘上黄色灯),有 Error(仪表盘上红色灯),甚至可以有 Verbosity,而且可以把各个子系统作为不同的事件源分别记录。这样,分析事故情况就很简单了…… 估计飞机上肯定是有这么一套东西的吧。

[INFO][2010-11-22 18:10:00.000 UTC-8]Subaru Legacy 2.5i
[INFO][2010-11-22 18:10:00.003 UTC-8]Battery OK. Voltage = 12.5V, Fuel=87%
[INFO][2010-11-22 18:10:01.000 UTC-8]Starting engine...
[INFO][2010-11-22 18:10:02:078 UTC-8]Engine started. RPM = 2345
[INFO][2010-11-22 18:10:02:099 UTC-8]Mileage: 144
[INFO][2010-11-22 18:10:02:143 UTC-8]ABS normal.
[INFO][2010-11-22 18:10:02:364 UTC-8]Traction control normal.
[INFO][2010-11-22 18:10:02:572 UTC-8]Parking brake normal.
...
...
...
[INFO][2010-11-22 18:10:02:913 UTC-8]ABS normal.
[INFO][2010-11-22 18:10:09:011 UTC-8]Brake pedal depressed.
[INFO][2010-11-22 18:10:10:033 UTC-8]Gear shifted into 'D'.
[INFO][2010-11-22 18:10:10:033 UTC-8]Brake pedal released.
...
...
...
[INFO][2010-11-22 18:13:07:898 UTC-8]1.0 mile(s). Speed = 20mph
...
...
...
[INFO][2010-11-22 18:16:13:325 UTC-8]Brake pedal depressed.
[WARN][2010-11-22 18:16:14:524 UTC-8]ABS engaged - release brake.
[WARN][2010-11-22 18:16:15:524 UTC-8]ABS engaged - apply brake.
[WARN][2010-11-22 18:16:15:624 UTC-8]ABS engaged - release brake.
[WARN][2010-11-22 18:16:16:624 UTC-8]ABS engaged - apply brake.
[WARN][2010-11-22 18:16:16:724 UTC-8]ABS engaged - release brake.
...
[WARN][2010-11-22 18:16:17:000 UTC-8]Skid detected. Traction control engaged.
...
...
[WARN][2010-11-22 18:16:20:000 UTC-8]Bang.

不算不知道

2010-10-20 – 23:46:14

来个文革数学题。

毛主席教导我们:“千万不要忘记阶级斗争。”现在我们来清算万恶的资本家乔剥皮是怎么剥削无产阶级工人张二狗的。

乔剥皮家的水果厂有 34,300 个工人。该厂今年实现获利 140.13 亿银元,运营成本 72.99 亿银元。

  1. 平均每个工人为工厂创造了多少价值? ((140.13+72.99)亿元/34300 = 621,341 元)
  2. 假设运营成本完全花在了人工及其相关事项上,i.e. 工人得到了这部分价值。那么平均每个工人能得到多少? (72.99 亿元/34300 = 212,799 元)
  3. 资本家从每个工人身上剥削了多少剩余价值? (140.13 亿元/34300 = 408,542 元)

答案刮开看。在万恶的旧社会,工人仅仅得到了自己所创造财富的 1/3,而剩下的 2/3 都被资本家残酷的无偿占有了。资本家进行资本主义生产,不是为了要享用工人为他生产的商品的使用价值,而是为了攫取工人生产的剩余价值,实现资本增殖。资本家不仅剥削产业工人,还残酷的剥削压榨殖民地人民,迫使工人增加劳动强度,而不管工人的死活。不知有多少工人就这样地葬送了生命。

无产阶级为争取缩短劳动日而进行的斗争,具有重要的意义。但是,这种斗争毕竟是一种经济斗争,它不可能从根本上改变无产阶级的地位。无产阶级要获得彻底的解放,必须把经济斗争发展为政治斗争,进行无产阶级革命,推翻资本主义制度。中国无产阶级在中国共产党的领导下,就是把争取缩短劳动日,改善生活状况的斗争,与民主革命的斗争任务结合起来,推翻了帝国主义、封建主义和官僚资本主义的反动统治,建立了无产阶级专政的社会主义制度。