Posts By Philip Ye

printf 中的格式化字符串

printf 系列函数(另有 fprintfsprintfsnprintf 等)在输出时使用了强大的格式化字符串。格式化字符串以一个 % 开始,以类型字段(dxf 等)结束,完整格式如下(除了 % 和类型之外均为可选字段,注意精度之前有一个句点):

%[参数][标志][宽度][.精度][长度]类型

参数

参数字段为 POSIX 扩展功能,非 C99 标准定义。使用 m$ 指定格式化字符串之后的第 m 个参数,从 1 开始编号。假如使用了参数字段,则所有的参数必须都至少使用一次,即从 1$n$ 都必须至少出现一次(其中 n 为格式化字符串之后的参数个数),否则编译时将产生如下警告:

warning: missing $ operand number in format [-Wformat=]

借助参数字段,可以实现参数的多次使用、乱序使用等,而不需要重复书写参数。例如:printf("%2$d %2$#x; %1$d %1$#x",16,17) 将输出 17 0x11; 16 0x10,两个参数都使用了两次,且先使用第二个参数(同时也使用了下一节的 # 标志)。

标志

  • -: 左对齐(默认为右对齐)
  • +: 给正数附加符号前缀(默认为正数没有任何前缀)
  • (空格): 给正数附加空格前缀(默认为正数没有任何前缀)
  • 0: 指定了宽度字段(见下文)且为右对齐时,前缀补 0(默认补空格;当使用 - 标志指定了左对齐时,0 标志失效)
  • #: 使用「备选格式」。对于 gG 类型,不省略小数点部分最后的 0;对于 fFeEgG 类型,总是输出小数点;对于 oxX 类型,分别在非零数值前附加 00x0X 前缀。上一节的例子中就使用了 # 标志。

ping 包长度及 MTU

ping 命令是测试网络是否连通最常用的命令,而无论是 Windows 还是 Linux,ping 命令都可以指定包长度,这对于验证网络设备的 MTU 非常有帮助。

先来看看在不同的操作系统下如何指定 ping 包长度及其各自的含义。

Windows

Windows 的 ping 命令通过 -l 参数指定包长度:

ping 192.168.1.1 -l 1000

使用 Wireshark 抓包看看:

可以看到 Length 为 1042 字节,比指定的包长度多了 42 字节。注意到 ICMP data 的长度正好是 1000 字节,加上 ICMP header 8 字节,IP header 20 字节,Ethernet header 14 字节,正好是 1042 字节。

也就是说,ping 命令指定的是 ICMP payload 的长度(不包括 ICMP header)。ping 命令作为 ICMP 协议的具体实现,这样的设定也符合逻辑。

当不使用 -l 参数时,默认的包长(ICMP payload)是 32 字节。

新西兰银蕨签证申请记录

银蕨签证是新西兰引进海外年轻技术人才的一种方式,每年 300 个名额。申请成功后首先发放的是银蕨求职签证(Silver Fern Job Search Visa),申请人必须在签证发放后 6 个月内登陆新西兰,在首次登陆后的 9 个月内找到满足薪资要求的技能性工作,之后即可申请有效期两年的银蕨实践工签(Silver Fern Practical Experience Work Visa),也就是通常所说的「银蕨二期签证」。入职 3 个月后,即可着手申请永居(有说法是拿到银蕨二期签证后可立即开始申请)。具体请参考 Jack Liu 博客

很久以前就听说新西兰的银蕨签证,在了解到每年针对全球只有 300 个名额后,想着全球顶尖人才那么多,我肯定申请不到。直到看到天维网公众号的这篇文章的这句话:

不过值得注意的一点就是,移民局要求的申请材料,你不需要在申请前准备好,当你真的抢到了宝贵的名额,移民局会给你 3 个月的时间来准备材料。
根据不少过来人介绍,这个时间足够了,哪怕你连雅思成绩都没有

于是我决定试试。

Bose QC30 使用体验

从 6 月 1 日入手 Bose QC30 到今天正好一个月,写写这一个月来的使用体验吧。

入手前的心路历程

最早是在推特上看到 Bose 的降噪耳机,隐约知道 Bose 有两款蓝牙降噪耳机,一款挂脖一款大耳罩,后来才知道具体型号分别是 QC30 和 QC35。

机缘巧合的是,牟老师春节后住在我们家时,用的正是 QC30,而后她去香港找七喜玩,七喜在试用过后也赞不绝口。我虽然口口声声说着没有刚需,但买一个蓝牙降噪耳机的种子已默默在心里种下~还设想了几个可以用得上降噪耳机的场景,比如办公室有同事在哼歌、午睡时有人打呼噜、地铁公交上有人外放音乐等等。

四月,罗罗来深圳出差,也在我们家住了几天,带来了他的 QC35,我也借机试用了一把(同时第一次知道了 ASMR)。

基于以下几点原因,我没有选择 QC35:

  • 深圳夏天天气那么热,戴大耳罩肯定不舒服。
  • 我的头小,大耳罩容易掉下来,尤其是低头的时候。
  • 大耳罩太拉风了,不符合我低调的风格。
  • 大耳罩体积较大,便携性不如 QC30。

五月,七喜也入手了 QC30,还帮雪碧买了一个(她要送给李先森的),这下让我更心痒了,时不时地关注下京东淘宝是不是有优惠。对比了香港和内地的价格,发现京东 618 活动时 QC30 价格最低。在 5 月 31 号晚上就守在电脑前准备秒杀,期间还反复问菲菲:

「我买了哈?」
「我可以买吗?」
「要不要给妳也买一个?」

Telegram 专用代理服务器 MTProxy 搭建

近日,Telegram 在俄罗斯遭封锁事件催生了基于其自有加密协议 MTProto 的代理服务器 MTProxy,官方源码使用 C 语言编写,托管于 TelegramMessenger/MTProxy。我试着在自己的 VPS 上搭建了一个,虽然官方文档非常简陋,但还算顺利。

服务器端编译

首先在 VPS (Ubuntu 18.04) 上克隆服务器端源码:

$ cd ~/dev/
$ git clone https://github.com/TelegramMessenger/MTProxy.git
$ cd MTProxy

编译之前需要安装必要的工具链和开发库:

$ sudo apt install build-essential libssl-dev zlib1g-dev

然后在 MTProxy 源码的根目录下直接执行 make 即可,编译出的可执行文件是 objs/bin/mtproto-proxy

之前的 README.md 没有说明需要安装的库文件,make 时在链接阶段有如下错误:

/usr/bin/x86_64-linux-gnu-ld: cannot find -lz

就是因为没有安装 zlib1g-dev 导致的。

服务器端运行

为简化说明,直接在编译结果目录中操作:

$ cd objs/bin/

获取 AES 密钥用于连接 Telegram 服务器:

$ curl -s https://core.telegram.org/getProxySecret -o proxy-secret

雅思备考两个月首战 7.0

好吧,我承认有点标题党了。我考的是 G 类雅思,按照惯例,先报分数,第一场在深圳考的:

第二场在悉尼:

11 月 30 号才决定要考,目标是均分 6.5,无单项分要求。当天晚上报了 1 月 20 号的深圳场,前后不到两个月时间。在准备了半个月之后,担心自己考不过,同时结合原定去澳洲过春节的计划,又报了 2 月 10 号的悉尼场。因为 2 月 9 号才能到悉尼,同时 G 类考试可选择的场次不多,所以特地选了非 IDP 考场,可以在笔试当天下午考口语。

从成绩单来看,除了 G 类阅读较简单而分数较高外,其它几个单项分数都不高,能够首战就刚好踩线上 7 也完全得益于阅读。简单总结下各个单项我是如何备考以及两场考试的经历吧。

Resolution 2018 (Philip)

时间紧迫,简单整理一下 2017 年的总结以及 2018 年的计划。

2017 总结

Resolution 2017 (Philip)》中制定的目标完成得并不好。

1、 每月输出一篇工作文档

工作相关的博客完成了 10 篇,其中尝试写了两篇英文博客。即便是技术相关,写得也比较吃力。另外,下半年的工作也没有做到很好的提炼。

2、 完成一次日语 N2 等级考试

7 月份考了一次日语 N2,单项分都达标了,总分差得有点多…… I tried, but I failed.

日语学习笔记整理到初级第 10 单元后也中断了。2018 还要继续学日语,继续和日语死磕。

3、 阅读至少 30 本书

说来惭愧,今年只看了 8 本书(参见《2017 年讀過的書》),其中《Mastering Bitcoin》在看第二版并整理笔记中;《How Google Works》一直没啃完……整理了几篇书摘,都是在下半年完成的。嗯,下半年没写工作总结,都在整理书摘了。

另外,电影看得也没有去年多了,参见《2017 年看過的電影》。

4、 和 Linda 一起去一趟台湾

这是今年的家庭旅行计划,逆时针从花莲到高雄,走马观光地浏览了大半圈。Linda 整理了花莲、宜兰和台北部分:

曼谷跨年计划也即将开始,相隔半年后马上要和 Linda 见面了,内心充满了小激动。

5、 制作一档播客节目

11 月份和七喜录了一期关于个人数字信息安全的播客,在荔枝上线了。本来打算放到又拍云并生成 iTunes 格式的 RSS 订阅列表,但因为突发事件暂时搁置了。

2018 计划

1、每月输出一篇技术相关文档

明年要多用英文写点东西,还是从技术博客开始。

8 月份在 Coursera 上完成了一个加密相关课程,明年的后继课程也已经报名。这部分内容会尽快整理出笔记。

博客后台还有几篇关于比特币、字体、网络协议等内容的草稿,也要尽快扫清。

2、阅读至少 10 本书

去年没有听 Linda 的建议,把目标定得太高。这次务实一点,先给自己定一个小目标,先看它 10 本书……

3、完成两次雅思考试

一月和二月各报了一场,正在紧张地备考当中。时间非常紧迫,12 月初因为奶奶的事情占用了不少时间,白天还得上班,只能晚上和周末有大片的时间准备。

现在每天都非常焦虑,担心自己考不好,担心重蹈日语考试的覆辙。真心佩服那些考过十几场雅思的烤鸭们,希望一切付出都会有回报。

4、去澳洲和 Linda 过春节

作为明年家庭旅行计划的一部分,「去妳去过的地方,看妳看过的风景」。

目前签证和机票都已搞定,酒店和行程安排就靠小助手 Linda 了,哈哈哈哈。

希望 2018 年我们的生活能有所改变,可以离梦想更近一步。

以上。我们明年元旦见。

费马大定理(下)

本文为西蒙・辛格《费马大定理》的书摘,共分上下两篇:

  • 上篇:包含原书第一、第二章的内容。
  • 下篇:包含原书第三~第八章的内容。

数学史上暗淡的一页

莱昂哈德・欧拉(Leonhard Euler)1707 年生于瑞士巴塞尔,是基督教新教加尔文宗的牧师保罗・欧拉(Paul Euler)的儿子。莱昂哈德服从父亲的意愿在巴塞尔大学学习神学和希伯来语。幸运的是,巴塞尔城的伯努利(Bernoullis)家族的丹尼尔和尼古拉是莱昂哈德・欧拉的好友,他们向保罗・欧拉呼吁,请求他允许莱昂哈德放弃教士的职务而选择数学。老欧拉过去曾经向老伯努利(即雅各布・伯努利)学习过数学,对这个家族怀有特殊的敬意,便勉强地同意了。欧拉不久就离开瑞士,在俄国沙皇那里开始了他的专业生涯,随后应普鲁士的腓特烈大帝的邀请到了柏林科学院,最终他又回到俄国,当时正是俄国女皇叶卡捷琳娜二世统治期间,在那里他度过了最后的岁月。

欧拉最重要的成就之一是对理论计算方法的发展,欧拉的计算方法适合于处理那些看上去是不可能解决的问题。太阳、地球和月亮的轨道计算问题,就是所谓的「三体问题」,直到今天仍然不可能得到精确解。但欧拉发展了一种方法,可以得到一个不完全但充分准确的解。这种方法(算法)首先求出一个粗糙但尚能使用的结果,然后将它反馈回算法中再产生一个更为精细的结果。然后这个精细的结果再反馈回算法中产生一个更加准确的结果,如此反复进行,经过百次或更多的迭代以后,欧拉就能提供月球的位置,这个结果用于航海是足够准确的了。欧拉关于月球位置的计算是在他失明期间完成的。

柯尼斯堡桥游戏:普鲁士城市柯尼斯堡(Königsberg)现为俄罗斯的加里宁格勒市,这个城市建立在普雷格尔河边上,由 4 个分离的、被 7 座桥连接起来的地区组成,如下图所示:

问题是能否设计一次旅行,穿越所有的 7 座桥却无须重复走过任何一座桥?欧拉论证了这样的旅行是不可能的:为了进行一次成功的旅行(即通过所有的桥仅一次),一个点应该连接着偶数条线。这是因为在旅行中当旅行者通过一块陆地时,他必须沿一座桥进入,然后沿不同的桥离开,但有两个例外——开始或结束时。在旅行开始时,旅行者离开一块陆地,仅需一座桥给他离开;而在旅行结束时,旅行者到达一块陆地,也仅需一座桥给他进入。如果旅行开始和结束于不同的位置,那么这两块陆地可以允许有奇数座桥,但如果旅行开始和结束于同一个地方,那么这个点(与所有其他的点一样)必须有偶数座桥。总结来说:对于任何桥网络,如果所有的陆地块都有偶数座桥,或者恰好有两个陆地块有奇数座桥,那么才有可能越过每座桥仅一次的完全的旅行。在柯尼斯堡的情形中,4 块陆地都连接着奇数座桥,所以不可能穿越每一座仅一次。

欧拉进一步发现了一条所有的网络的基本定理,即所谓的网络公式:V + R – L = 1,其中 V 是网络中顶点(即交点)的个数,R 是网络中区域(即围成的部分)的个数,L 是网络中连线的个数。论证网络公式时,欧拉从最简单的网络即一个单一的点开始,V = 1,R = L = 0,公式显然成立。然后对这个单一的点扩充,就需要增加一条线。这条线可以将已有的顶点与自己连接,或者它可以将已有的顶点与另一个新的顶点连接。前一种情况:当增加一条线后,生成了一个新的区域,增加的区域抵消了增加的连线,网络公式仍然成立。以这种方式增加更多的连线也同样成立,因为每一条新的连线会制造一个新的区域。后一种情况:增加的线将原来的点与一个新的顶点连接,增加的顶点抵消了增加的连线,网络公式仍然成立。以这种方式增加更多的连线也同样成立,因为每一条新的连线会制造一个新的顶点。

在《算术》的另一个注记中,费马给出了费马大定理对于 4 次幂的证明,而欧拉在 1753 年给普鲁士数学家克里斯蒂安・哥德巴赫(Chritian Goldbach)的信中宣布,他采用费马的无穷递降法并引入虚数 i 的方法成功地证明了 3 次幂的情形。100 多年来,这是第一次有人针对费马的挑战成功地取得了进展。

根据让・勒隆・达朗贝尔(Jean le Rond d’Alembert)的建议,约瑟夫—路易・拉格朗日(Joseph-Louis Lagrange)接替欧拉成为腓特烈大帝宫廷中的数学家。欧拉回到了俄国,叶卡捷琳娜二世迎回了她的「数学的独眼巨人」。

费马大定理(上)

费马大定理》是西蒙・辛格的第一本书,相比《密码故事》来说,这本书的中译本虽然封面上把 Fermat 错误地拼写成 Fremat,正文中也有几处小错误,但瑕不掩瑜,全书整体的翻译质量好很多,尤其是将人名、地名等专有名词翻译出来的同时,还在括弧中保留了英文,可方便地据此搜索相关资料并延伸阅读。

本文为西蒙・辛格《费马大定理》的书摘,共分上下两篇:

  • 上篇:包含原书第一、第二章的内容。
  • 下篇:包含原书第三~第八章的内容。

我想我就在这里结束

1993 年 6 月 23 日,英国剑桥大学牛顿研究所,安德鲁・怀尔斯(Andrew Wiles)向全世界最杰出的数学家讲述他对费马大定理(Fermat’s Last Theorem)的解法。剑桥正是怀尔斯是家乡,这里是他出生成长的地方。他在 20 世纪 80 年代移民到美国,在普林斯顿大学任教授。这次牛顿研究所举行的研讨会的题目是「L-函数和算术」,只有怀尔斯意识到 L-函数可能握有解决费马大定理的钥匙。

1963 年,10 岁的安德鲁・怀尔斯在弥尔顿路上的图书馆发现了埃里克・坦普尔・贝尔(Eric Temple Bell)写的《大问题》(The Last Problem),其中讲述了费马大定理的起源及形成,由此迷上了费马大定理,立志要解决它。

费马大定理立足于毕达哥拉斯(Pythagoras)定理:

在一个直角三角形中,斜边的平方等于两直角边的平方之和。

萨摩斯岛(Samos)的毕达哥拉斯是数学史上最具影响但又是最神秘的人物之一。他研究了一些特殊的数的性质、它们之间的关系以及它们的组成方式。他生活在公元前 6 世纪,游历时从埃及人和巴比伦人那里学到了许多数学技能和工具。这两个古老的民族当时已经超越了简单计数的范围而能够进行复杂的计算,这使他们能建立复杂的记账系统和建造独具匠心的建筑物,但他们将数学看成仅仅是解决实际问题的一种工具,而没有人会费神去寻求隐藏在背后的逻辑。

经历 20 年的周游后,毕达哥拉斯回到爱琴海中的萨摩斯岛,想要建立一所学校致力于哲学研究,特别是研究他新近获得的一些数学法则。但僭王波利克拉特斯(Polycrates)在毕达哥拉斯外出期间已将曾经自由的萨摩斯岛变成了一个不容异说的保守的社会,并邀请毕达哥拉斯加入宫廷,但遭到毕达哥拉斯的拒绝。毕达哥拉斯离开了城市,选择了岛上边远地区的一个山洞。他花钱使一个小男孩成为他的第一名学生,这名学生根据有些历史学家的观点可能也叫毕达哥拉斯。这名学生后来是第一个建议运动员应该吃肉以增强自己体质的人,并因此而出名。学生每出席一节课,老师要付给他 3 个小银币。几个星期后,学生最初对学习的勉强已转变成对知识的热情,即使毕达哥拉斯佯装付不起金钱无法继续上课时,学生也表示宁可付钱受教育。遗憾的是,这是毕达哥拉斯在萨摩斯岛上仅有的一个信徒。

由于毕达哥拉斯关于社会改革的观点不受欢迎,他被迫离开萨摩斯岛,来到意大利南部的克罗敦(Groton),并在米洛(Milo)的赞助下建立了毕达哥拉斯兄弟会——一个有 600 名追随者的帮会。一旦参加兄弟会后,每个成员就必须将其一切财产捐献给公共基金,如果离开该会,可收到相当于他们最初捐献的两倍的财产,并为其竖立一场墓碑以志纪念。兄弟会的每个成员被迫宣誓永不向外界泄露他们的任何数学发现,甚至在毕达哥拉斯死后,还有一个兄弟会成员因为公开宣布发现一种由 12 个正五边形构成的正十二面体而被淹死。兄弟会奉行平等主义,吸收了几名姐妹。毕达哥拉斯最喜欢的学生是米洛的女儿,美丽的西诺(Theano),两人最终结婚了。建立兄弟会后不久,毕达哥拉斯撰造了一个名词「哲学家」(philosopher),定义为「献身于发现生活本身的意义和目的的人」。

毕达哥拉斯缔造了一种社会精神,它改变了数学的进程。兄弟会实际上是一个宗教性社团组织,他们崇拜的偶像之一是数,他们相信,通过了解数与数之间的关系,他们能够提示宇宙的神圣的秘密,使他们自己更接近神。

密码故事(下)

本系列为《密码故事》的书摘,共有上、中、下三篇,各篇链接及包含内容如下:

  • 上篇:单字母替换密码,多字母替换密码。
  • 中篇:加密的机械化,恩格玛机及其破解,象形文字和楔形文字的破解。
  • 下篇:公开密钥,PGP,量子密钥分发。

公开密钥

除了恩格玛机之外,德国还有一套更强大的加密法,称为洛伦兹密码(Lorenz cipher),用来加密希特勒和他的军官之间的通讯。布莱切利的两位破解员,约翰・蒂尔特曼(John Tiltman)和比尔・塔特(Bill Tutte)发现了洛伦兹密码的一个破绽,需要综合寻找、匹配、数据分析和谨慎的判断,而「炸弹」很难变通地应付洛伦兹密码的精妙之处。而布莱切利的数学家马克斯・纽曼(Max Newman)基于图灵的「万能机器」的概念,发明了可以针对不同问题进行自我调节的机器,现在我们称之为「可编程计算机」。1943 年,工程师汤米・弗劳尔斯(Tommy Flowers)无视布莱切利高级官员的怀疑,根据纽曼的蓝图,花了 10 个月时间,制造了科洛希斯(Colossus computer,其中总共有 1500 个电子管。事实上,科洛希斯正是现代数字计算机的前身。

然而,在二战结束后,汤米・弗劳尔斯根据命令将科洛希斯及其蓝图销毁,世界上第一台计算机的设计图就此消失。1945 年,宾夕法尼亚大学的约翰・墨西里(John Mauchly)和 J・蒲利斯普・埃克特(J. Presper Eckert)完成了 ENIAC,它含有 18000 个电子管,每秒能计算 5000 次。几十年来,ENIAC 而非科洛希斯被认为是计算机之母。

用计算机加密和机器加密只有三个重要的区别:

  • 密码机受限于实际建造中的困难,而计算机可以模拟出任何无限复杂的机器。
  • 速度上的区别:电子设备比机器的扰频器运转起来要快得多。
  • 最重要的区别:计算机加密的是数字而非字母。

即便如此,加密过程仍然是按照古老的原则进行的,这些原则就是移位和替换。每次加密,无论多么复杂,都可以还原成一些简单操作的组合。

随着越来越多的公司采用计算机,公司之间的通讯加密也越来越频繁,就出现了加密标准化的问题。1973 年,美国国立标准局正式征求一套标准的加密方案,能够使企业之间进行秘密通讯。IBM 的托马斯・J・沃森实验室(Thomas J Watson)的霍斯特・菲斯特尔(Horst Feistel)发明卢斯福密码机(Lucifer cipher)。1976 年,56 位版本的卢斯福密码机被国家安全局正式采用,称之为数据加密标准(Data Encryption Standard,即 DES)。选用 56 位版本(密钥数目 1018)是因为国家安全局相信这样的密钥对民间通讯来说是安全的,因为没有一个民间组织拥有如此强大的计算机能够在一个合理的时间内检查每个密钥,但国家安全局拥有世界上最快的计算机资源,刚好能破解卢斯福的密钥。

卢斯福系统的加密步骤如下所述:首先,电文翻译成一长段二进制数字串。然后,以每 64 个数字为一个单位,分解这段数字串。每个单位数字串分别独立加密。第三步,我们把注意力集中在每个单位数字串上。把 64 个数字像洗牌那样分成两组,每组 32 个数字,分别把它们叫做左 0 和右 0。右 0 中的数字加入「切碎机函数」中进行复杂的替换。然后,把「切碎」后的右 0 加到左 0 上,形成新的一组 32 个数字的序列,称作右 1。把最开始的右 0 标记为左 1。这一系列的操作称为一个「回合」。然后整个操作又重复做一次,不同的只是这一次以右 1 和左 1 开始,得到的数字序列称为右 2 和左 2。加密过程总共要进行 16 个「回合」。这个过程就像是和面一样:试想在一大块面上写着信息,首先,将这块面分成 64 厘米长的小块;然后,挑出其中的一半碾压后折叠起来,再加到另一半上拉长,从而形成一个新的面块。这个过程不断地重复,直到消息文字彻底地被面块混合起来。经过 16 个回合的「揉面」后,密文发送出去。另一端的接收者收到密文后,将加密过程反过来进行,从而解码出明文。「切碎」的具体实施方法是可以变化的,它取决于发送者和接收者达成的密钥。换言之,只要密钥不同,同样的电文可以用成千上万种不同的方式加密。

除了加密标准化问题之外,密码通讯中存在的另一个问题是「密钥分发」。20 世纪 70 年代,银行尝试雇用专职的密钥分发员,他们带着一个锁着的箱子(padlocked briefcase)走遍全世界,亲手将密钥交给客户。二战时,德国高级指挥部每个月都需要分发《每日密钥》月刊给所有的恩格玛机操作员。美国政府的密钥是 COMSEC(通讯安全局)掌管和分发的。20 世纪 70 年代,COMSEC 每天分发的密钥数以吨计,当装载着 COMSEC 密钥的船靠港时,密码分发员会到甲板上收集各种卡片、纸带以及软盘和其他一切贮存密钥的介质,再把它们分发给客户。计算机改变了密码的实施方式,但 20 世纪密码学最伟大的革命是发明了密钥分发的技巧,这被认为是两千年来自单字母替换密码发明以后最伟大的成就。