《九章算术》,一本成书于东汉初期、汇总了中国先秦至汉代数学成就的著作。Python版本的《九章算术》,以编程的方式诠释《九章》,通过《九章》学习编程。
简练精致的文言、清晰明了的代码,相辅相成、相合相融。“观阴阳之割裂,总算术之根源”,“析理以辞,解体用图”,用严谨的态度在计算机上再现古人之思,在古算法的阐述中体现计算机编程之想、之美。
最近有个 GitHub 项目火了 —— 文言编程语言 / wenyan-lang。
这一项目并不是简单的将程序中的英文字符换成了中文,而是利用 NLP 的一些技术,将文言文程序语法转换到 JAVAScript 或 Python 运行。
来看看 文言版的“Hello world” 怎么写:
吾有一數。曰三。名之曰「甲」。
為是「甲」遍。
吾有一言。曰「「問天地好在。」」。書之。
云云。
运行:
問天地好在。
問天地好在。
問天地好在。
文言文编程肯定没有 abc,改用甲乙丙:
吾有一數。曰三。名之曰「甲」。
有數五十。名之曰「大衍」。
吾有一言。曰「「噫吁戲」」。名之曰「乙」。
true/false 改为阳/阴,类型变成了“爻”:
吾有一爻。曰陰。名之曰「丙」。
if 判断:
若三不大於五者。乃得「「想當然耳」」。若非。乃得「「怪哉」」也。
循环:
為是百遍。⋯⋯云云。
恆為是。⋯⋯云云。
乃止。
看了这些代码,网友戏称:照这样下去,《九章算术》就是一本算法导论;《孙子兵法》就是一本安全攻防;《易经》大概是一本二进制逆向……
其实,国内还真的有人研究《九章算术》,并且以编程的方式诠释这时隔千年的经典数学著作。
她就是timedot,真名胡洁,拥有近二十年的IT从业和管理经验,担任过开发、测试、配置、测试经理、QA经理、高级项目经理等多个职务,具备扎实的理论基础和丰富的实战经验,使用过的编程语言有:PB、C、C++、Java、Perl、Python。
同时他也是一名热爱传统文化的程序员,遵崇“科学艺术本相通,科技人文可相融”的创作理念,将致力于为计算机科学注入更多的人文气息。
《九章算术》是我国现存的最古老的数学著作之一。据初步考证,《九章》大约成书于东汉初期,汇总了中国先秦至汉代的数学成就。
《九章》是一本问题集,以问答的形式,汇集并分析了当时人们在实践中所碰到的数学问题。全书共计246个问题202术,按问题性质分为方田、粟米、衰分、少广、商功、均输、盈不足、方程、勾股9章,其中各章在解决实际问题时,都有明确的计算方法:“术”。
《九章》成书后,历经众人传抄、删改,时有变动。直至魏晋时代,刘徽为《九章》作注,基本成为流传后世基本的定本。而后至唐代,李淳风等人为其补注后,该书成为了算术专科的主要课本。之后,此书传习不绝。“九章”二字,也成了中国数学的代名词。
为什么说《九章》中的“术”其实可以对应计算机科学中的“算法”呢?我们来看一个实际的例子——里田术。
“问题一今有田广一里,从一里。问为田几何?
答曰:三顷七十五亩。
问题二又有田广二里,从三里。问为田几何?
答曰:二十二顷五十亩”
什么意思呢?
简单翻译一下就是:
问题一,有一块方形田地,长为1里,宽为1里,其面积是多少?
答:3顷75亩。
问题二,又有方形田地,其长为2里,宽为3里,其面积是多少?
答:22顷55亩。
古人的思想,其实和我们现代科技又是相通的,在计算机上,我们可以再现古人之思。
比如这段话,也可以用我们设计优雅、明确、简单的编程语言Python来翻译。
1、自定义函数
我们可以把里田术定义成自己的一个函数。函数定义包括函数的名字以及函数被调用时运行的语句序列集。下面是这个函数的源码,如图所示。
函数的第一行叫做header(头),其余部分叫做body(体)。header以一个冒号结束,body可以包含任意数量的语句。body里的所有语句必须缩进,缩进可以选择两个空格、4个空格或一个tab,无论选择哪一种,body中每一条语句的缩进必须一致、必须对齐。
函数的命名规则和变量命名规则一样:字母、数字、下划线是合法的,但第1个字符不能是数字。你不可以用关键字作为函数名,也应尽量避免函数名和已有的变量名同名。
提示
关键字是编程语言里事先定义的、有特别意义的标识符,例如:def是一个关键字,表示这是一个函数定义;return也是一个关键字,表示返回函数结果。
2、注释
一个程序是用代码这种形式语言编写的,很密集,只看一部分代码,经常很难弄明白这部分代码是做什么的,以及为什么要这么做。
程序越大越复杂,阅读理解就会越困难。所以,在程序中必须增加注释,注释采用自然语言对程序的功能进行描述。注释以#标志开始,Python解释器会将注释标示为红色,会忽略从#到行尾的文本(这部分文本Python解释器不会执行)。
3、程序剖析
程序第一部分为两条赋值语句,一句赋值ji_li(积里),一句赋值mu_shu(亩数)。第二部分是亩数转换,第三部分连接字符串返回结果。
1.赋值语句
ji_li=guang*cong#广从里数相乘得积里
mu_shu=375*ji_li#以三百七十五乘之,即亩数
第一条赋值语句将传入的参数guang、cong相乘的结果赋值于变量ji_li。
第二条赋值语句将ji_li与375相乘的结果赋值于变量mu_shu。
2.亩数转换
#1顷=100亩,亩数转换成顷和亩
qing=int(mu_shu/100)
mu=mu_shu%100
mu_shu/100是将亩数转换成顷,结果是一个浮点数,如375/100→3.75;int(mu_shu/100)调用了int()函数,将mu_shu/100的结果截取成整数,如int(3.75)→3,即顷的整数部分。
mu_shu%100是取模运算,%是一种算术运算符,用于取除法运算的余数,例如:375%100→75(即375÷100商为3余75,这个余数75就是%运算的结果),也即亩数转换成顷后剩余的亩。
所以,上面两句代码的含义如下。
亩数(mu_shu)若为375,顷(qing)=3,亩(mu)=75,
也就是:375亩 = 3顷75亩
3.字符串连接
#连接成字符串并返回结果
jie_guo=str(qing)+'顷'+str(mu)+'亩'
returnjie_guo
这里的“+”是“字符串连接”运算符,用于把字符串连接起来。表达式str(qing) + '顷' + str(mu) + '亩'求值为一个新的字符串,这个新的字符串连接了4个字符串里的文本:str(qing) 、'顷' 、str(mu) 、'亩'。其中str(qing)、str(mu)调用了str()函数,将整数qing、mu转换成了字符串。
“+”运算符要么是加法算术运算符,要么是字符串连接运算符。它所连接的值要么都是整数或浮点数,要么都是字符串,不能又有整数、浮点数,又有字符串。表达式str(qing) + '顷' + str(mu) + '亩',如果写成qing+'顷' + mu + '亩',就会出错。因为qing、mu是整数,而'顷'和 '亩'是字符串,整数和字符串之间不能进行“+”运算符操作。
赋值语句jie_guo = str(qing) + '顷' + str(mu) + '亩',把连接成的新的字符串赋值给了变量jie_guo。
return jie_guo 将jie_guo作为函数li_tian_shu的返回值返回
4、运行结果
在IDLE中输入这个函数,最后输入一个空行结束。完成这个函数定义后,我们可以调用它来解决里田术问题一、问题二,运行结果如图所示。
li_tian_shu(1,1)解决问题一“广一里,从一里”,也就是传递给函数的参数为:guang=1、cong=1,结果为3顷75亩;
li_tian_shu(2,3)解决问题二“广二里,从三里”,也就是传递给函数的参数为:guang=2、cong=3,结果为22顷50亩;
作为中国数学历史上经典著作,其中精妙的算法构思值得程序员学习。而这本书用Python语言来表述《九章》中的各种“术”、各种数学思想,也通过《九章》来学习Python语言、学习编程、学习算法思维。
通过学习《九章》各卷通用的计算方法,由浅到深覆盖了Python的编程基础。这些计算方法包括:
卷一方田:合分术、减分术、平分术、割圆术;
卷二粟米:今有术、其率术、反其率术;
卷三衰分:衰分术、返衰术;
卷四少广:少广术、开方术、开立方术;
卷六均输:均输术;
卷七盈不足:盈不足术;
卷八方程:方程术、正负术;
卷九勾股:勾股术。
在对各术的讲解过程中,加深对上篇各种编程概念的理解,呈现各种编程技巧,同步提升Python编程能力。各术的讲解包括:图解、中文注释、数学术语和程序代码,程序代码中包含对应的文言注释,程序代码的右边批注代码的编程技巧。每一个“术”的开始,都附有Python编程要点。