从古埃及分数开始

来源:互联网 发布:华东电脑旗下华讯网络 编辑:程序博客网 时间:2024/04/30 12:16

昨晚实在无聊,半夜爬起来看BBC的《数学的故事》。当那个长得像Daniel Craig的大叔以极其诡异的手法解决了古埃及劳苦人民的分饼问题后,我瞬间被震撼了,虽然好像自己以前曾经做过,但是一点印象都没了。

几个概念:

  • 我们把0到1之间的分数叫做真分数
  • 分子为1的真分数称为单位分数

问题描述:

  • 如何将任意真分数x拆解为有限个单位分数之和?

考虑到可能有多个解法,在此我们要求单位分数尽可能大。

我们首先考虑的是用1/2,1/3,1/4,……一个个去试,如果这个单位分数1/n比x小,1/n就入选了。接着用同样方法从1/(n+1)开始找x - 1/n的解。能不能一次定位n呢?

既然要求x - 1/n > 0 且n尽可能小,那么n就是大于1/x的最小整数,即n = ceiling[1/x]。以下是Mathematica解法:

aux[x_] := 1/Ceiling[1/x]toS := ToString[#, InputForm] &g[x_] := If[IntegerQ[1/x], x // toS,  (f[x] // toS) <> "+" <> g[x - aux[x]]]

aux()和toS()这两个函数都是打酱油的,g()才是主角。如果x本身就是单位分数,那么省事了(这也是递归的终点),但如果不是,则照上面的办法求解。

P.S. 好久没用Mathematica了,还是很快就上手了。但发现几个问题:

  • Mathematica的自定义函数名不允许含下划线,因为下划线有特殊含义(以前专门研究过,可惜每次过后就忘)。这样我就不能像Ruby那样把函数取名为to_s,有点小不爽。
  • Mathematica好像不能像Ruby那样在字符串内求值#{...}。所以我之后用丑陋的StringJoin(即<>)。

接下来,很自然地想问:这个算法能不能保证在有限步内终止,即真分数能不能表示为有限个尽可能大的单位分数之和。注意,联想到无穷级数,你能很轻易找到某个真分数可以表示为无穷个单位分数之和,比如1/3 = 1/4 + 1/16 + 1/64 + ……

而一个无理数可能是不能表示为有限个单位分数之和的。因为只要将这有限个分数通分就能将这个无理数写成某个分式,那么它就不是无理数了。

然后的然后,我还没想出来-_-!