以清华简《算表》为例
清华简《算表》是目前所知我国最早的计算器,它的发现在我国数学史上占据重要意义。《算表》于2013年12月由中西书局出版,为清华简第四种。李学勤先生在2014年1月14日的《中国文化报》上,对《算表》进行了大体介绍,指出它是“迄今为止所见的最早算具”,能快速进行100以内的整数乘除,并“还能计算包含分数1/2的两位数乘法”①。全面介绍《算表》功能的,是李均明、冯立异二位先生的论文《清华简《算表》的形制特征与运算方法》(以下简称《运算》)②、《清华简《算表》的功能及其在数学史上的意义》(以下简称《功能》)③。《运算》和《功能》称,该表可以实现乘法(含整数乘法和分数乘法)、乘方、除法、开平方四种运算。
李、冯二位先生的研究非常精彩,让人叹为观止,但似乎缺少了一些重要说明:他们推测《算表》的功能时,所依据的原则是什么?他们如何确定《算表》是否具有某种功能的?比如,《运算》说,《算表》“可能还用于开平方运算,但我们不能确定这一算表当时已被用于开方这样的复杂运算”。判断《算表》是否有开平方运算功能的依据是什
————————
① 李学勤.《筮法》《别卦》与《算表》[N].中国文化报,2014-1-14(8).
② 李均明,冯立异.清华简《算表》的形制特征与运算方法[J].自然科学史研究,2014(1):1-17.下文所论二位先生的研究均出于此,不再出注。
③ 冯立异.清华简《算表》的功能及其在数学史上的意义[J].科学,2016(3):40-46.
么?仅仅是今人所认为的“复杂”与否吗?今人认为是“复杂”的算法,对古人来说,就一定是“复杂”的吗?这些都是很重要的原则性问题,而且可以对类似情况产生有益的借鉴。因此,笔者需要先进行一定的探讨。
笔者认为,有两种推测思路。一种是尝试所有的可能性,从而得到最大的可能范围。这种思路的问题在于:今人的数学知识往往比古人多,存在有意无意拔高古人成就的可能性。《运算》对《算表》的开平方功能采取审慎的态度,原因可能也正在于此。另一种是用二重证据法,即不以现在的数学知识为推演的基础,而还原到古人所处的时代,以当时或之前的数学知识、数学思维为推演的基础,进行研究。具体说来,我们要对今人的推演,进行两个方面的检验:第一,要看古人有没有相关的运算知识。如果现有的数学史材料没有发现这些知识,就需要谨慎得出结论,或者是暂不得出结论。第二,要看古人的运算习惯是什么。如果有相关的知识,但是很少用,那么我们得出结论的时候,也需要很谨慎。二重证据法坚持有一分证据,说一分话,证据不足时,只能存疑。这是一种科学的态度。当然,严格按照上述二重证据法来研究,也存在问题:由于古代文献流传下来的非常少,可以说是九牛一毛。这样做,容易将范围缩得太小,而且很有可能将有重要突破的独特新材料忽略,从而造成对古人的成就过于低估的问题。这也是前辈学者用疑古精神来研究古书时,所遇到的问题。
因此,较为合理的做法是:先用二重证据法,以古人的数学知识、数学思维进行推演,在缺少相关旁证的情况下,再尝试各种可能性。笔者循此思路,对《算表》进行一些小的探讨。具体说来,笔者将以目前所能见到的秦汉时期的若干数学材料———岳麓秦简《数》、张家山汉简《算数书》和《九章算术》,以及《孙子算经》里的筹算知识等为依据,重新考察这一问题。凡是在这些材料中出现过的算法,不管算法怎么难,都认为是有可能应用在《算表》上的;反之,就会取谨慎的态度。
一、清华简《算表》的开平方运算
《运算》以2304为例,解说《算表》的开平方功能:
先在对角线中找出小于2304但与其最近的数“1600”,将通过“1600”的纵横引线分别延伸至从第一功能区,所见数字40即确定了平方根之十位数。以1600减2116得516,即2304-1600=704,在纵横引线找到最接近但小于704一半(352)的数320,通过另两条分别过两个320的正交引线可确定平方根之个位数字为8。而320的2倍是640,704-640=64=8²,因此正好被开尽。因此可求得,
=48。①
《运算》认为《算表》可能有开平方的功能,但不是很确定:“就此表具备的条件而言,采用与上述除法类似的方法并借助对角线可对9801(99×99)以内的整数开平方,因此它可能还用于开平方运算,但我们不能确定这一算表当时已被用于开方这样的复杂运算,这一问题尚待进一步探讨。”在旁证不足的情况下,这一论述无疑是审慎而可取的。其中的原因,除了《运算》所说的开平方计算是“复杂运算”之外,可能更重要的原因是:《运算》所描述的开平方运算,用的是《九章算术》中的方法,而《九章算术》成书的两汉之际距离《算表》所
——————————
① 这段话里有两个错误。第一,“以1600减2116得516”,这句话莫名其妙,原文里没有2116,也不该有516。笔者怀疑,《运算》本来以2116为例(平方根为46),不知为何,中途改成以2304为例(平方根为48)。改动时,“以1600减2116得516”这句话,应该改为“以1600减2304得704”,由于疏忽而未改。第二,“分别延伸至从第一功能区”中的“从”字是衍文,应删。
在的战国时期,相差了二百年以上,未必能作为《算表》具有开平方功能的证据。
我们在张家山汉简《算数书》中,找到比《九章算术》更早的开平方计算。《算数书》的拥有者为汉初某低级官吏,该官吏的下葬时代在汉朝吕后二年(前186)。《算数书》的算题为摘抄性质,是广泛地从各种书籍中摘录而来,并非原创,我们可以得出两个跟本书有关的重要结论:第一,《算数书》的算题与算法的来源时间必然不晚于吕后二年,学界一般推测为战国时期或秦代。也就是说,其年代与《算表》非常相近,可以作为我们研究《算表》的参考。第二,《算数书》的内容为低级官吏抄录而来,说明这些算题在当时较为常见,流传较广。如此高水平的《算表》,其制作者肯定是知道《算数书》中记载的数学知识的。也就是说,《算数书》的知识可以用于推算《算表》的功能。
张家山汉简《算数书》中,有一道算题名为“方田”,其实质为整数的开平方近似计算,其内容如下:
方田 田一亩方几何步?曰:方十五步卅一分步十五。术曰:方十五步不足十五步,方十六步有余十六步。曰:并赢、不足以为法,不足子乘赢母,赢子乘不足母,并以为实,复之,如启广之术。①
这道算题实际上是求240的平方根是多少。计算方法是:容易知道,平方根位于15、16之间。15²=225,不足240,所以称15为“不足母”,余数240-15²=15称为“不足子”。16²=256,超过240,所以称16为“赢母”,余数16²-240=16称为“赢子”。以“不足母+赢母”
——————————
① 张家山二四七号汉墓竹简整理小组.张家山汉墓竹简二四七号墓(释文修订本)[M].北京:文物出版社,2006:157. 20
作为分母,以“不足子×赢母+赢子×不足母”作为分子,得到的分数就是其近似值。
《算数书》计算开平方的方法非常巧妙:将复杂的开平方运算变为简单的乘方运算,找到“不足母”和“赢母”,这样就极大地降低了计算的难度。如果不能开尽,则用盈不足术取得近似值。用这种方法在《算表》上计算2304的平方根,计算方法为:
(1)先在对角线中找出小于2304但与其最近的数“1600”,将通过“1600”的纵横引线分别延伸至第一功能区,所见数字40即确定了平方根之十位数。下面尝试找到小于平方根的“不足母”和大于平方根的“赢母”。
(2)因数“40”“1”两条引出线与因数“40”“1”两条引出线纵横相交于1600、40、1四个交点,将此四数相加为“1681”,小于2304,继续尝试。
(3)因数“40”“2”两条引出线与因数“40”“2”两条引出线纵横相交于1600、80、80、4四个交点,将此四数相加为“1764”,小于2304,继续尝试。
(4)因数“40”“3”两条引出线与因数“40”“3”两条引出线纵横相交于1600、120、120、9四个交点,将此四数相加为“1849”,小于2304,继续尝试。
(5)因数“40”“4”两条引出线与因数“40”“4”两条引出线纵横相交于1600、160、160、16四个交点,将此四数相加为“1936”,小于2304,继续尝试。
(6)因数“40”“5”两条引出线与因数“40”“5”两条引出线纵横相交于1600、200、25四个交点,将此四数相加为“2025”,小于2304,继续尝试。
(7)因数“40”“6”两条引出线与因数“40”“6”两条引出线纵
横相交于1600、240、240、36四个交点,将此四数相加为“2116”,小于2304,继续尝试。
(8)因数“40”“7”两条引出线与因数“40”“7”两条引出线纵横相交于1600、280、280、49四个交点,将此四数相加为“2209”,小于2304,继续尝试。
(9)因数“40”“8”两条引出线与因数“40”“8”两条引出线纵横相交于1600、320、320、64四个交点,将此四数相加为“2304”。可见48即为平方根。
对于《算数书》的开平方算法而言,计算2304的平方根实在是太过简单的事情,就连2305等无法开尽的平方根,它都有办法处理。其计算方法为:
(1)先计算平方根的十位数,结果为40:在对角线中找出小于2305但与其最近的数“1600”,将通过“1600”的纵横引线分别延伸至第一功能区,所见数字40即确定了平方根之十位数。
(2)计算41的平方,看其与2305的关系:因子“40”“1”两条引出线与因子“40”“1”两条引出线纵横相交于1600、40、40、1四个交点,将此四数相加为“1681”,即41²=1681,小于2305,继续尝试。
(3)以此类推,分别计算42²、43²、44²…48²、49²与2305的关系,发现482为2304,小于2305,49²为2401,大于2305,则个位数为8。
(4)由(3)可知,“不足母”为48,“不足子”为2305-48²=1,“赢母”为49,“赢子”为49²-2305=96,则最终的结果为(1×49+48×96)/(48+49)=48 。
需要注意的是,今天的数学计算追求绝对准确,所以会觉得古人可能没法计算2305的平方根,但古人所追求的首先是实用,而不是绝对准确。比如,秦汉时期的π取值为3,《算数书》中甚至有π取值为4的情况,误差较大,就是出于实用的目的,而非绝对准确。《算数书》计算整数开平方运算,所采用的也是类似的并不完全准确的实用方法。这样就导致《运算》眼中的“复杂运算”,在古人的近似计算中却相当简单。我想,这种思路上的差别可能是李、冯二位先生不太敢相信《算表》可以被用于计算整数开平方计算的原因。
下面再讨论《运算》的开平方计算和《九章算术》的开方术的异同。《九章算术》的开方术内容如下:
术曰:置积为实。借一算步之,超一等。议所得,以一乘所借一算为法,而以除。除已,倍法为定法。其复除。折法而下。复置结算步之如初,以复议一乘之,所得副,以加定法,以除。以所得副从定法。复除折下如前。若开之不尽者为不可开,当以面命之。若实有分者,通内分子为定实,乃开之,讫,开其母报除。若母不可开者,又以母乘定实,乃开之,讫,令如母而一。①
按照《九章算术》的记载,我们可以采用如下方法在《算表》上计算2304的平方根:
(1)以两位为单位,将2304分成23和04两个部分,并由此得知结果的整数部分为两位数。
(2)通过《算表》,找到平方最接近23的数,为4,则结果的十位数部分为4。
(3)23-4²=7,则下一次参与计算的部分为704。
(4)将十位数部分乘以20,得80(可以通过《算表》进行计算)。假设个位数部分为x,则x=704÷(80+x)
——————————————
① 郭书春.九章算术新校 [M].合肥:中国科学技术大学出版社,2014:125-126.
x取整数。我们可以暂时忽略(80+x)中的x,通过《算表》,发现80×8=640,比704小,且最接近704。
(5)704-(80+8)×8=0,说明平方根恰好为48。
我们将这一过程用类似《运算》的语言进行描述:
先在对角线中找出小于23但与其最近的数“16”,将通过“16”的纵横引线分别延伸至第一功能区,所见数字4即确定了平方根之十位数。以16减23得7,下一步进行计算的数即704。下一步参加运算的两个乘数之一是十位数的20倍,即80。在纵横引线找到最接近但小于704的数640,通过另两条分别过两个640的正交引线可确定平方根之个位数字为8。(80+8)×8=704,因此正好被开尽。因此可求得, =48。
《九章算术》的计算过程与《运算》基本相同,主要区别是:第一,《九章算术》的开平方计算以两位数为单位。这是因为两位数开平方后对应一位整数,这样就可以用当时人所熟知的九九乘法直接得出答案。《运算》则直接进行千位计算,结果虽然相同,但是《运算》并不符合古人的计算习惯。这可能是为了照顾今人的计算习惯而进行的微调。
第二,《九章算术》针对704进行计算,《运算》则针对704的一半进行计算。
第三,最后一步的计算也略有差异。
《算数书》距离《算表》的时代较近,计算简便,但在开不尽的情况下,结果有误差。《九章算术》距离《算表》的时代较远,计算较为复杂,但在开不尽的情况下,结果较为准确。
二、清华简《算表》的分数乘法
《运算》以42 X22 为例,讨论了《算表》的分数运算。在《算表》上的操作是:
把因数42 分解为“40”“2”“ ”三数。把因数“20 ”分解为“20”“2”“ ”三数。因数“40”“2” “ ”三条引出线与因不“20”、“2”、 “ ”三条引出线纵横相交于800、80、20、40、4、1、10、 、为“956 ”即上式乘积。
对应的数学原理则是:42 ×22 =(40+2+ )×(20+2+ )=40×20+40×2+40× ++2×20+2×2+2×2× + ×20+ ×2+ × =800+80+20+40+4+1+10+1+ =956
如果《运算》的例题中,没有小数部分,那么这种计算方法是成立的。这是因为整数乘法,所依据的就是乘法的分配律,而且我们可以在《孙子算经》和《夏侯阳算经》中找到证据,《算数书》的“里田”也能体现这一点。
下面以记载最为完备的《孙子算经》为例,进行说明:
凡乘之法,重置其位。上下相观,上位有十步至十,有百步至百,有千步至千。以上命下,所得之数列于中位。言十即过,不满自如。上位乘讫者先去之。下位乘讫者则俱退之。六不积,五不只。上下相乘,至尽则已。①
可以翻译为:
用算筹进行乘法运算时,首先要将被乘数和乘数分别置于上、下位。将下位的最低位和上位的最高位对齐——被乘数最高位是十位,就和十位对齐;被乘数最高位是百位,就和百位对齐;被乘数最高位是千位,就和千位对齐。每一步所得的结果,都要放在中位(要和下位参与操作的数位对齐)。如果结果超过10,向前进位;不超过,不进位。每次只用上位的最高位来乘下位,乘完后,就把它去掉。乘完一轮之后,下位向后退一位。6不能用6根算筹来表示。5不能只用一根算筹来表示。上位和下位相乘,直到乘完为止。
很显然,这里的整数乘法,所依据的就是乘法的分配律,和《运算》的记载很相似。《算数书》的“里田”也能体现这一点:
里田 里田术曰:里乘里,里也,广、从(纵)各一里,即直(置)一因而三之,有(又)三五之,即为田三顷十(七十)五亩。其广、从(纵)不等者,先以里相乘,已,乃因而三之,有(又)三五之,乃成。今有广二百廿里,从(纵)三百五十里,为田廿八万八千七百五十顷。直(置)提
————————
① 郭书春,刘钝.算经十书孙子算经M.沈阳:辽宁教育出版社,1998:2. 26
封以此为之。
一曰:里而乘里,里也,壹三,而三五之,即顷亩数也。有(又)曰:里乘里,里也,因而三之;以里之下即予廿五因而三之,亦其顷亩数也。曰:广一里,从(纵)一里为田三顷十(七十)五亩。①
这道算题是已知长方形土地的两边边长(以里为单位),求其面积(若干顷若干亩)。由于1里×1里=375亩或者说是3顷75亩,所以计算方法都是土地的长×宽×375。需要注意的是最后一段,有一种计算方法是将375亩分成两个部分:3顷和75亩,因此计算方法就变成了:长×宽×3顷+长×宽×75亩。这就有了整数乘法分配律的意思,会对我们的思考提供借鉴。也就是说,秦汉时期应该是存在整数乘法的分配律的。
问题在于,《运算》多了分数部分,这就从整数运算变成了分数运算。我们需要考虑的问题是:古人是怎么计算分数乘法的?用的是与《运算》类似的分配律吗?下面,我们进行详细考察。
(1)《算数书》中的分数乘法的计算方法,体现在“相乘”“分乘”两则。
“相乘”的计算方法是:“乘分之术曰:母乘母为法,子相乘为实。”② 也就是说,分数相乘,要让分子相乘,分母也相乘,并不涉及分配律。
“分乘”的计算方法是:“分乘之术皆曰:母相乘为法,子相乘为实。”③ 也就是说,分数相乘,要将分数都化成假分数,然后让分子相乘,分母也相乘,并不涉及分配律。
————————
① 彭浩,张家山汉简《算数书》注释M.北京:科学出版社,2001:125-127.
② 彭浩.张家山汉简《算数书》注释 [M].北京:科学出版社,2001:38.
③ 彭浩.张家山汉简《算数书》注释[M].北京;科学出版社,2001;40.
(2)《九章算术》中的分数乘法的计算方法,体现在“乘分”和“大广田”两则。
“乘分”的计算方法是:“术曰:母相乘为法,子相乘为实,实如法而一。”① 也就是说,分数相乘,要让分子相乘,分母也相乘;如果计算结果是假分数,要化为带分数。需要注意的是,这里的两个乘数可以是假分数,这是因为,如果两个乘数都是真分数,那计算结果就一定是真分数,不需要化为带分数,“实如法而一”这句话就没有必要存在。这里的计算方法并不涉及分配律。
“大广田”的计算方法是:“分母各乘其全,分子从之,相乘为实。分母相乘为法。实如法而一。”② 也就是说,分数相乘,要先将分母通分,然后分子相乘,分母也相乘;如果计算结果是假分数,要化为带分数。与上条一样,这里的两个乘数可以是假分数。计算方法也不涉及分配律。
(3)岳麓秦简《数》中有简单的分数乘法口诀,但是描述没有分数乘法的计算方法。③
综上所述,我们可以发现,《算数书》《九章算术》中的分数乘法均只有一种计算方法:将带整数的分数化为假分数,然后分子乘分子,分母乘分母,即可得到结果,并不涉及《运算》所描述的那种分配律。
同样以42 ×22 为例,《算数书》《九章算术》中的分数乘法用——《算表》来计算,其操作过程是:
因数“40”“2”两条引出线与因数“2”的引出线纵横相
————————
① 郭书春.九章算术新校[M].合肥:中国科学技术大学出版社,2014:17.
② 郭书春.九章算术新校M.合肥:中国科学技术大学出版社,2014:18.
③ 朱汉民,陈松长.岳麓书院秦简(贰)M.上海:上海辞书出版社,2011.
交于80、4两个交点,将此两数相加为84,再加上1,合为85,即为被乘数的分母。
因数“20”“2”两条引出线与因数“2”的引出线纵横相交于40、4两个交点,将此两数相加为44,再加上1,合为45,即为乘数的分母。
因数“2”的引出线与因数“2”的引出线纵横相交于4,即为结果的分母。
因数“80”“5”两条引出线与因数“40”“5”两条引出线纵横相交于3200、400、200、25四个交点,将此四数相加为3825,即为结果的分子。
从第一功能区(任选横栏或纵行)数字“4”处分别引出除数线。在除数线诸数中找出距离3825的前两位38最近的数,所见为“9”。38-4×9=2。在除数线诸数中找出距离22最近的数,所见为“5”。22-4×5=2。在除数线诸数中找出距离25最近的数,所见为“6”。25-4×6=1。“9”“5”“6”即为结果的整数部分,余数“1”即为结果的分子部分。①
对应的数学原理是:
42 ×22 = × = × = = =
= = (百位)+ =900+ =900+ (十位)+ =900+50+ =900+50+6+ =956
——————
① 本段描述参考了《孙子算经》中的整数除法运算。古人擅长九九乘法,而对超过九九乘法之外的计算比较陌生。因此,用38除以4,符合古人的运算习惯,且有《孙子算经》为证,是可取的,而不能直接用3825或者382除以4,虽然这样更加简单,但是缺乏文献上的依据,也不符合古人的运算习惯。
很显然,该计算过程要比《运算》烦琐很多,需要先将乘数和被乘数都化为假分数,再相乘,再将结果由假分数化为带整数的真分数。而《运算》通过乘法的分配律,可以直接得出若干数值,将这些数值相加,即可得到最终结果。这说明,《运算》很可能是今天的学者用今天的数学知识、数学思维而推演出来的简便方法,缺乏传世数学文献和出土数学文献上的证据,要么不是秦汉时期计算分数的常用计算方法,要么根本就在秦汉时期不存在。笔者认为,似乎应该持较为谨慎的态度,还是采取《算数书》《九章算术》中的烦琐的计算方法为好。当然,《运算》的主要目的在于说明功能,细节上的小问题无关宏旨。
三、清华简《算表》的整数除法运算
《运算》以3808÷68为例,描述了整数除法运算,其运算步骤如下:
将除数“68”分解为“60”与“8”。
从第一功能区(任选横栏或纵行)数字“60”与“8”处分别引出除数线。
在两条除数线诸数中找出同位置之两数相加等于或小于但离被除数最近的数,所见为“3000+400”。
将“3000”与“400”的连线延伸至另一功能栏,所见“50”为商数之十位数值。
以被除数减上述二数即3808-3400=408,接着在上述两条除数线找出同位置之两数相加与余数“408”相等的数,所见为“360+48”。
将“360”与“48”的连线延伸至功能栏,所见为“6”为商数之个位数值。
对应的数学原理是:3800÷68=3808÷(60+8)=(3000+400+3800-3000-400)÷(60+8)=(3000+400)÷(60+8)+408÷(60+8)=50+(360+48)÷(60+8)=50+6=56。
我们用简略的语言描述一下背后的数学原理:
我们假设计算结果对应的个位数是x,十位数是y(x,y均为0到9的整数),那么本算题就是首先确定y,找到满足如下条件的y:y×10 ×68≤3808,且(y+1)×10×68>3808。然后确定x,找到满足如下条件的x:xx68=3808-y×10×68。当然,如果不能整除,那就是要寻找:x ×68≤3808-y×10×68且(x+1)×68>3808-y×10×68。68是分母,余数是分子。
《数》《算数书》《九章算术》中均无整数除法的计算方法。这可能是因为,整数除法是基础知识,过于简单,不必赘述。《孙子算经》中有相应的记载,内容如下:
凡除之法:与乘正异。乘得在中央,除得在上方,假令六为法,百为实,以六除百,当进之二等,令在正百下。以六除一,则法多而实少,不可除,故当退就十位,以法除实,言一六而折百为四十,故可除。若实多法少,自当百之,不当复退,故或步法十者,置于十百位(头位有空绝者,法退二位)。余法皆如乘时,实有余者,以法命之,以法为母,实余为子。①
————————
① 郭书春,刘钝.算经十书孙子算经M.沈阳:辽宁教育出版社,1998:2.
我们以3808÷68为例,描述了《孙子算经》中的整数除法运算,其运算步骤如下:
将除数“68”分解为“60”与“8”。
从第一功能区(任选横栏或纵行)数字“60”与“8”处分别引出除数线。
由于3808的前两位38小于68,所以第一步参与运算的被除数为3808的前三位,即380。在两条除数线诸数中找出同位置之两数相加等于或小于但离380最近的数,所见为“300+40”。
将“300”与“40”的连线延伸至另一功能栏,所见“5”为商数之十位数值。
以被除数的前三位减上述二数即380-340=40。由此可知,下一步参加运算的被除数是408。接着在上述两条除数线找出同位置之两数相加与余数“408”相等的数,所见为“360+48”。
将“360”与“48”的连线延伸至功能栏,所见为“6”为商数之个位数值。
对应的数学原理是:3800÷68=380÷(60+8)(十位)+8(待处理)=(300+40+380-300-40)÷(60+8)(十位)+8(待处理)=(300+40)÷(60+8)(十位)+8(待处理)=50+(360+48)÷(60+8)=50+6=56。
《运算》与《孙子算经》的记载基本一致,因而是可信的。但其中也存在细微的差异:《孙子算经》的除法是由左到右逐位进行的,先看38能否被68除,不能,再看380能否被68除,这样可以保证每次得到
的结果都是个位数。对古人来说,这种计算的每一步都是比较简单的。《运算》却是直接用3808除以68,以得到结果的最高位数,虽然计算过程更简单,但是恐怕不符合古人的计算习惯。