跳转到内容

Python 和 Ruby 中的数学/Python 中的分数

来自 Wikibooks,开放世界的开放书籍

分数模块的官方 Python 文档在此

将非整数的数字写成分数可以追溯到埃及人和巴比伦人,早于小数的使用。只要分母不是 10 的幂,我们仍然经常使用分数,尽管它们可能被某种程度上隐藏起来。

  1. 如果我们说一个人的身高是 5 英尺 7 英寸,那么他以英尺为单位的身高是(一英尺有十二英寸);
  2. 当我们说现在是早上 8:13 时,我们的意思是自午夜以来已经过去了正好小时(493 分钟)。
  3. 当罗密欧抱怨他已经等了超过三刻钟来等茱丽叶时,他正用分数表达他等待时间的长度……
  4. 概率通常以分数表示(通常是埃及分数),例如“我中彩票的机会是一千万分之一”,或者“赔率是 5 比 1”。
  5. 统计数据也可以用分数表示:“每 6 个人中有 5 个人穿毛衣”。

方程 0.2+0.5=0.7 可以写成,但方程无法使用十进制数字精确地写出来。Python 将 1/2+1/3 的结果给出为 0.8333333333333333;尽管所有数字都存在,但这并不是精确的答案。

对于分数的精确计算,Python 有一个fractions模块。要使用本章中的脚本,请从以下行开始

from fractions import *

这将从分数模块导入所有内容。

获取分数

[编辑 | 编辑源代码]

Python中输入分数,使用Fraction(n,d),记住要从fractions模块导入它。

from fractions import *
a = Fraction(24,10)
print(a)             # 12/5

我们发现 Python 在实例化时自动简化了分数

如果将 0 作为分母输入,则分数将不会创建,并且会出现错误消息。我们不能将数字除以 0。

计算出分数后,我们可以获取它的分子分母

from fractions import *
a = Fraction(24,10)
print(a.numerator)
print(a.denominator)

当然,的分子在简化后不再是 24。

要获取分数的值(它的分子除以它的分母),我们可以将其转换为“浮点数”——这指的是计算机通常如何存储非整数的数字(作为“浮点数”)。

from fractions import *
a = Fraction(24,10)
print(float(a))

我们也可以将实数转换为分数,但如果该数字是不能在二进制中精确表示的数字,则结果可能会令人惊讶。

from fractions import *
a = Fraction.from_float(1.2)
print(a)

而不是,我们得到分数。这是因为不能在二进制中精确存储,就像不能精确地写成小数一样。在这种情况下,我们可以通过直接从小数到分数,而无需计算机将其转换为二进制来获得更好的结果。

from fractions import *
a = Fraction('1.2')
print(a)

分数的运算写法与其他数字相同,但结果通常是分数。

一元运算

[编辑 | 编辑源代码]

要取分数的反,在其前面加上-符号。例如

from fractions import *
a = Fraction(2,-3)
print(-a)

求倒数

[编辑 | 编辑源代码]

要找到分数的倒数,用 1 除以它。

from fractions import *
a = Fraction(5,4)
print(1/a)

两个分数的和是一个分数。

from fractions import *
a = Fraction(34,21)
b = Fraction(21,13)
print(a+b)

两个分数的差是一个分数。

from fractions import *
a = Fraction(34,21)
b = Fraction(21,13)
print(a-b)

两个分数的积是一个分数。

from fractions import *
a = Fraction(34,21)
b = Fraction(21,13)
print(a*b)

两个分数的商是一个分数(只要第二个分数不为零)。

from fractions import *
a = Fraction(34,21)
b = Fraction(21,13)
print(a/b)

分数也可以求余数(或)。结果是一个分数。

from fractions import *
a = Fraction(32,7)
b = Fraction(7,2)
print(a%b)

如果指数是整数,则分数的幂是一个分数。

from fractions import *
a = Fraction(3,2)
print(a**12)
print(a**(-1))

但如果指数是实数,则分数的幂是一个实数。

from fractions import *
a = Fraction(9,4)
print(a**0.5)

Farey 约简

[编辑 | 编辑源代码]

使用 Python 的 fractions 模块可以轻松创建Farey 序列

from fractions import *
def Farey(a,b):
    n = a.numerator+b.numerator
    d = a.denominator+b.denominator
    return Fraction(n,d)


a = Fraction(3,4)
b = Fraction(1,13)
print(Farey(a,b))

这可以用来生成Stern-Brocot 树;这可能不会解释太多,但它在数学中有所应用。

埃及分数

[编辑 | 编辑源代码]

埃及分数由一系列整数的倒数组成;埃及人以不使用分子而闻名。任何分数都可以写成埃及分数的和,我们可以使用斐波那契算法为任何分数找到这样的和。在下面的 Python 示例中,该算法生成一个分数列表,所有分数的分子都为 1,这些分数加起来等于给定的分数 f。由于 f 可能大于 1,因此我们从一个整数开始列表。

from fractions import *
from math import ceil

def egypt(f):
    e = int(f)
    f -= e
    parts = [e]
    while(f.numerator>1):
        e = Fraction(1, int(ceil(1/f)))
        parts.append(e)
        f -= e
    parts.append(f)
    return parts

a = Fraction(21,13)
print(egypt(a))            # [1, Fraction(1, 2), Fraction(1, 9), Fraction(1, 234)]
print(sum(egypt(a))        # 21/13 (confirming that these fractions add up to the original value)

上面代码的一些解释:每个埃及分数的分母应该是一个整数,并且大于分数 f 的倒数,以便算法收敛。一种解决方案是将倒数向下舍入到整数(使用 int)并加 1。但是,如果 f 的倒数是整数,则加 1 会导致一个无限级数。因此,我们使用 ceil 函数,向上舍入到整数。因此

  1. 我们必须从 math 模块导入此函数。
  2. ceil(1/f) 的结果是一个实数,而不是整数,因此我们不能直接在分数中使用它(Python 会报错)。我们使用 int 将其转换为整数。

最后,我们必须将最后一个埃及分数添加到列表中,以完成级数。

运行上面的脚本,我们发现

华夏公益教科书