本文选自计算机科学经典著作《编码:隐匿在计算机软硬件背后的语言》。
语言只不过是一种编码。
我们之中的许多人在学校里至少都学过一门外语。所以我们知道,英文中的“cat”(猫)在其他语言中可以写做gato、chat、Katze、KOIIIK或kátta。
然而,数字似乎并不是那么容易随文化的不同而改变。不论我们说什么语言,或对数字使用什么样的发音,在这个星球上几乎所有人都用以下方式来书写数字:
1 2 3 4 5 6 7 8 9 10
这难道不就是数学被称做“通用语言”的理由么?
数字当然是我们平常所能接触到的一种最抽象的编码。当我们看到数字:
3
不需要立刻将它与任何事物联系起来。我们可能会联想到3个苹果或者3个别的什么东西。但是当我们从上下文中得知该数字表示的是某个小孩的生日、电视频道、曲棍球赛的得分或蛋糕食谱中面粉的杯数时,也能够像认为它代表3个苹果时一样自然。因为数字最开始产生时就很抽象,所以对于我们来说,理解这样一个问题会有一点困难。这个问题就是如下数量的苹果:
并不一定要用符号“3”来表示。同样可以用“11”来表示。
首先让我们遗忘数字10原有的那些特性。大多数文明都是建立在以10为基数的数字系统上的(有的时候是以5为基数),这种情况并不奇怪。最开始,人们用自己的手指来计数。如果我们人类有8个或12个手指,那么我们的计数方式就会和现在有所不同。英语中Digit(数字)这个词同时也有手指、脚趾的意思,并且还有数字的意思,这并不是巧合。而five(五)和fist(拳头)这两个单词的拥有相同的词根也是同样的道理。
在这个意义上,以10为基数或使用十进制数字系统完全是随意的。而且,英文中还对基于十的数字赋予了几乎神奇的意义,并且给了它们特有的名字:十个一年是一个十年(decade);十个十年是一个世纪(century);十个世纪就是一个千年(millennium)。一千个一千就是一个百万(million);一千个百万就是一个十亿(billion)。以下都是10的各次幂。
10^1 = 10
10^2 = 100
10^3 = 1000(千)
10^4 = 10, 000
10^5 = 100, 000
10^6 = 1, 000, 000(百万)
10^7 = 10, 000, 000
10^8 = 100, 000, 000
10^9 = 1, 000, 000, 000(十亿)
大多数历史学家认为数字最初起源于对事物的计数,例如:人数、财产或商业交易的计数等。举个例子,如果有一个人有四只鸭子,用图画表示为:
后来,专门负责画鸭子的这个人会想:“为什么我非得要画四只鸭子?为什么我不画一只鸭子再用划线或其他事物来表示有四只鸭子呢?”
然后直到有一天,出现了一个人,他拥有27只鸭子,这种划线的方法就显得很可笑了。
有人说:“必须想一种更好的方法。”于是一个数字系统就诞生了。
所有早期的数字系统中,只有罗马数字沿用到了今天。我们可以在表盘上、纪念碑和雕像的日期上、一些书的页码中,或者在条款的概述中看到罗马数字,而令人最烦恼的就是电影的版权声明(必须足够快地破译位于演职人员表末尾的“MCMLIII”才能知道这部影片是哪一年发行的)。
27只鸭子用罗马数字表示为:
这个概念很容易理解:X表示10个划线,V表示5个划线。
沿用到今天的罗马数字符号有:
I V X L C D M
这里,字母I表示1,可以看做是一个划线或者一根伸出的手指。字母V像一只手,表示5。两个V是一个X,代表数字10。L是50。C来自单词centum,表示100。D是500。最后一个,M来自于拉丁文mille,意为1000。
尽管我们可能不会认同,但在很长一段时间内,罗马数字被人们看做是易于加减的,这也是为什么罗马数字在欧洲作记账之用一直沿用到今天。实际上,两个罗马数字相加的时候只不过是利用几个规则将两个数合并,这个规则是:五个I是一个V,两个V是一个X,五个X是一个L,以此类推。
但是用罗马数字进行乘法和除法却很复杂。很多其他早期数字系统(像古希腊数字系统)和罗马数字系统相似,它们在用于复杂运算方面同样也存在一定的不足。尽管古希腊人发明的非凡的几何学至今仍然是高中生的一门课程,但古希腊人并不是以代数而著称的。
如今我们所用的数字系统通常被称为阿拉伯数字,也可以称为印度-阿拉伯数字系统。它起源于印度,被阿拉伯数学家带入欧洲。其中最著名的就是波斯数学家穆罕默德•伊本穆萨•奥瑞兹穆(根据这个人的名字衍生出英文单词“algorithm”,算法),他在公元825年左右写了一本关于代数学的书,其中就用到了印度的计数系统。其拉丁文译本可追溯到公元1120年,它对加速整个欧洲从罗马数字到阿拉伯数字系统的转变有着重要影响。
阿拉伯数字系统不同于先前的数字系统,体现在以下三点。
是的,就是0。小小的一个零无疑是数字和数学史上最重要的发明之一。它支持位置计数法,因此可以将25、205和250区分开来。0也简化了与位置无关的数字系统中的一些非常复杂的运算,尤其是乘法和除法。
阿拉伯数字的整体结构可以以我们读数字的方式来展现。以4825为例,我们读做“四千八百二十五”,意思就是:
四千
八百
二十
五
或者,我们也可以将此结构以如下写法写出:
4825 = 4000 + 800 + 20 + 5
或者,对其进一步分解,可以将数字写做:
4825 = 4 × 1000 +
8 × 100 +
2 × 10 +
5 × 1
或者,以10的整数次幂的形式来表示:
4825 = 4 × 10^3 +
8 × 10^2 +
2 × 10^1 +
5 × 10^0
记住任何数的0次幂都等于1。
一个多位数中的每一位都有其各自特定的意义,如下图所示。这7个方格能代表0~9,999,999中的任何一个数字。
每个位置代表10的一个整数次幂。我们不需要一个专门的符号来表示数字“10”,因为我们可以将1放在不同的位置,并用0作为占位符。
另一个好处就是,以同样的方式将数字置于小数点右边可以表示分数。数字42,705.684就是:
4 × 10, 000 +
2 × 1000 +
7 × 100 +
0 × 10 +
5 × 1 +
6 ÷ 10 +
8 ÷ 100 +
4 ÷ 1000
这个数也可以写为不含除法的形式,如下:
4 × 10, 000 +
2 × 1000 +
7 × 100 +
0 × 10 +
5 × 1 +
6 × 0.1 +
8 × 0.01 +
4 × 0.001
或用10的幂的形式来表示:
4 × 10^4 +
2 × 10^3 +
7 × 10^2 +
0 × 10^1 +
5 × 10^0 +
6 × 10^-1 +
8 × 10^-2 +
4 × 10^-3
注意,10的幂指数是如何减小到0再变为负数的。
我们知道,3加4等于7。类似地,30加40等于70,300加400等于700,3000加4000等于7000。这就是阿拉伯数字的“闪光”之处。任何长度的十进制数相加时,只要根据一种方法将问题分成几步即可,而每个步骤最多只是将两个一位数字相加而已。这就是为什么以前有人会强迫你记住加法表的原因。
从最上边的一行和最左边的一列分别找出要相加的两个数字,这一行与这一列的交叉点就是所要得到的和。例如,4加6等于10。
同样,当你想将两个十进制数相乘的时候,方法可能稍微复杂些,但是你仍然只需要将问题分解成几步,做加法和一位数的乘法即可。在你的小学时代你一定也被要求必须记住下面的乘法表。
位置计数系统的好处并不在于它有多么好用,而在于对非十进制的系统而言,它仍然是易于实现计数的。我们现有的计数系统并不适用于每种情况。以10为基数的数字系统最大的问题是它对于卡通人物没有任何意义。大多数卡通人物每只手(或爪子)只有4根手指,因此它们需要一个以8为基数的计数系统。而有意思的是,许多我们在十进制数中所了解到的知识同样适合卡通朋友们所钟爱的八进制计数系统。
图 书 推 荐
▊《编码:隐匿在计算机软硬件背后的语言》
【美】Charles Petzold 著
左飞,薛佟佟 译
这是一本讲述计算机工作原理的书。不过,你千万不要因为“工作原理”之类的字眼就武断地认为,它是晦涩而难懂的。作者用丰富的想象和清晰的笔墨将看似繁杂的理论阐述得通俗易懂,你丝毫不会感到枯燥和生硬。更重要的是,你会因此而获得对计算机工作原理较深刻的理解。这种理解不是抽象层面上的,而是具有一定深度的,这种深度甚至不逊于“电气工程师”和“程序员”的理解。
(扫码了解本书详情)
▊《labuladong的算法小抄》
付东来(@labuladong) 著
本书专攻算法刷题,训练算法思维,应对算法笔试。注重用套路和框架思维解决问题,以不变应万变。
(扫码了解本书详情)
如果喜欢本文
欢迎 在看丨留言丨分享至朋友圈 三连
热文推荐
本文分享自 博文视点Broadview 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!