Python中的更快的fractions模块

3 投票
4 回答
2026 浏览
提问于 2025-04-17 10:11

有没有一个比fractions模块更快的替代品,比如说一个cFractions模块?就像cDecimal模块是Decimal模块的更快版本一样。因为fractions模块运行得太慢了。

4 个回答

1

很遗憾,目前没有不需要编译外部依赖的C语言等价方案。根据你的需求,我做了一个简单的代码示例:https://gist.github.com/mscuthbert/f22942537ebbba2c31d4,可能会对你有帮助。

这个示例提供了一个函数 opFrac(num),它可以选择性地把整数、浮点数或分数转换成浮点数或分数,并且可以设置分母的上限(我用的是65535,因为我处理的是小分数);如果这个浮点数可以在二进制中精确表示(也就是说,它是某个2的幂的倍数),那么就不做任何改变。否则就把它转换成分数。同样地,如果分数可以在二进制中精确表示,我们就把它转换成浮点数;否则就不做改变。

这里的 Fraction(float).limit_denominator(x) 调用被提取成一个辅助函数 _preFracLimitDenominator,这个函数只会创建一个 Fraction 对象,而不是通常情况下会创建的三个对象。

这个示例的使用场景不多,但在有需要的地方,效果非常好。比如在我的项目 music21 中,我们主要处理的音符通常是在一个节拍(整数)上,或者在半拍、四分之一拍、八分之一拍等(这些在二进制中可以精确表示),但在一些比较少见的情况下,当音符的放置(偏移)或持续时间是,比如说,三分之一拍或五分之一拍时,我们就会遇到浮点数转换的问题,这导致了一些难以发现的bug。我们的测试用例在使用浮点数偏移和持续时间时需要350秒,而把所有的转换成分数后,时间增加到了1100秒——这完全不可接受。后来我们改用可选的分数和快速创建分数的方法,时间又回到了360秒,只损失了3%的性能。

如果你能接受有时候使用浮点数,有时候使用分数,这可能是一个不错的选择。

4

可以使用 这个链接

它使用了GMP这个多精度库,可以快速进行整数和有理数的计算。

注意:我也是这个项目的维护者。

6

我也遇到了缺少这个包的问题,于是决定自己实现一个叫做 cfractions 的包(源代码可以在 Github 上找到)。

我们只需要安装它

/path/to/python3 -m pip install cfractions

然后在你的模块中把 fractions 替换成 cfractions,就这么简单。

主要特点包括:

  • 占用更少的内存

    >>> from cfractions import Fraction
    >>> import sys
    >>> sys.getsizeof(Fraction())
    32
    

    相比于

    >>> from fractions import Fraction
    >>> import sys
    >>> sys.getsizeof(Fraction())
    48
    

    所以它基本上是一个普通的 Python object 加上 2 个指针,用来表示分子和分母。

  • 速度更快:

    • 可以从一对 int 创建 从一对整数创建
    • 可以从一个 float 创建 从一个浮点数创建
    • 可以从 str 创建 从字符串创建
    • 可以对 n 个实例求和 n个实例的和
    • 可以对 n 个实例求积 n个实例的积 或者如果我们看看相对性能 n个实例的相对积 我们可以看到 fractions.Fraction 的表现非常好,太棒了!

    注意:我使用了 perfplot,所有基准测试都在 Python3.9.4 上运行。

  • 支持 Python3.5+

  • 使用普通的 Python C API,没有额外的依赖,

  • 可以从分子/分母对、单个 int/float/任何 numbers.Rational 值、str(从 版本 1.4.0 开始)构建,

  • 支持所有算术和比较操作,

  • 字符串表示(包括 __repr____str__),

  • 支持 picklecopy

  • 不可变性和可哈希性,

  • 可以与 intfloat 进行操作(对于后者,将 Fraction 实例转换为 float,就像 fractions.Fraction 一样),

  • 支持 PyPy(通过回退到 fractions.Fraction 代理),

  • 使用 Hypothesis 框架 进行所有操作的基于属性的测试。

它不包括的内容:

  • 不支持与 complex 进行操作。

撰写回答