如何在Python中将分数写成小数并保留x位小数?

3
我希望您能为我提供一个方法,可以将python Fraction()类型以任意数量小数位的方式输出。我已查看了Python文档中关于Fraction和Decimal的内容,但似乎无法进行转换或输出Fraction。
因此,我正在寻找一种打印输出的方法。
Fraction(5, 7)

as

0.7142857142857142857142857142857142857142857142857142

替代

>> float(Fraction(5, 7))
0.7142857142857143

指定DP的数量。

4个回答

6
您可以使用 Decimal 类实现任意精度。
from fractions import Fraction
from decimal import localcontext, Decimal

def print_fraction(f, digits):
    assert(f.imag == 0)

    # Automatically reset the Decimal settings
    with localcontext() as ctx:
        ctx.prec = digits
        print(Decimal(f.numerator) / Decimal(f.denominator))

f = Fraction(5, 7)
print_fraction(f, 52)

这将打印出0.7142857142857142857142857142857142857142857142857143

1
@TimPietzcker 实际上这是一个很好的观点——或许可以问问库的作者Mark Dickinson,他常出现在Python开发者及用户列表中。我认为Decimal完全可以接受Fraction并执行AndiDog在此处所做的操作。 - Jon Clements
@JonClements:声明:我不是十进制库的作者;只是过去曾经为它做出了重要贡献的众多人之一。 :-) - Mark Dickinson
4
如果从分数构建Decimal,则与Decimal构造函数当前的工作方式不同:目前,所有构造(从浮点数、字符串、整数、元组)都是精确的,不进行四舍五入,也不利用当前的精度或取整模式。从分数构建则需要考虑四舍五入。然后有一个棘手的问题:对于大整数nDecimal(n) != Decimal(Fraction(n))是否可以接受。因此,最好避免从分数隐式构建Decimal - Mark Dickinson
@MarkDickinson 如果我错误地将您描述为该库的“作者”,请接受我的道歉 - 只是当涉及到 Decimal 时,我就会想到 “Mark Dickinson” - 因为在我看过的有关此主题的列表中,您是最活跃的 :) - Jon Clements
@JonClements:没问题!我只是想避免因别人的工作而受到赞扬或责备。 :-) - Mark Dickinson
显示剩余6条评论

2
from decimal   import Decimal, localcontext
from fractions import Fraction

def format_fraction(f, precision):
    with localcontext() as ctx:
        ctx.prec = precision
        return str(Decimal(f.numerator) / f.denominator)

f = Fraction(5, 7)
print(format_fraction(f, 52))

这与上面有何不同?分母也应该转换为十进制吗? - Jack TC
@JackTC:有3个不同之处(最重要的是localcontext()(请参见其他问题的编辑历史记录))。没有必要将分母转换为Decimal,请尝试一下。 - jfs
似乎精度指定的是总位数,而不是小数点后的位数。format_fraction(Fraction( 88554379,66000),2) == '1.3E+3'。我该如何使其返回'1341.73' - Janus Troelsen

0
def format_fraction(f, precision):
    if f == 0: return "0"
    s = str(int(f)) + "."
    f -= int(f)
    with localcontext() as ctx:
        ctx.prec = precision
        s += str(Decimal(f.numerator) / f.denominator).partition(".")[2]
    return s

这将在format_fraction(Fraction(88554379,66000),2)上返回"1341.73",而不是"1.3E+3"

这个方法对于略小于0的负数无效:format_fraction(Fraction(-5, 11), 2)输出0.45。我认为现在人们会使用Decimal.quantize来实现这个功能。 - dennis

-3

你可以使用字符串格式化来实现。通过这种方式,你总是可以编写自己的包装函数。

>>> '%.64f' % (5 / 7.0)
'0.7142857142857143015746146375022362917661666870117187500000000000'

是的,你说得没错。你看过结果了吗?从第16位小数开始就出现错误了。 - Tim Pietzcker
我其实没有注意到那个。 - Christian Witts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接