Search code examples
pythonstring-formattingfractions

fractions.Fraction f-strings as float with __format__


When using a fraction.Fraction in an f-string I would expect to be able to format it as a float. However I get a TypeError:

from fractions import Fraction
f = Fraction('11/10')
f'{f} as float {f:.3f}'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported format string passed to Fraction.__format__

It would seem that the floating point format specs could/should be supported for Fractions.

Interestingly they are for Decimal:

from decimal import Decimal
f = Decimal('1.1')
f'{f} as float {f:.3f}'

Is there a reason this doesn't work for Fraction?

And yes, I know I could do f'{f} as float {float(f):.3f}' but I'm asking why that's required.


Solution

  • As of version 3.12 Python now supports __format__. It also illustrates why initializing with a float is inaccurate due to many decimal values not being able to be represented accurately in binary floating point:

    import sys
    from fractions import Fraction
    
    print(sys.version)
    f1 = Fraction(11/10)    # float initialization
    f2 = Fraction('11/10')  # string (accurate) initialization
    f3 = Fraction(11, 10)   # also accurate initialization
    print(f'{f1} as float {f1:.20f}')
    print(f'{f2} as float {f2:.20f}')
    print(f'{f3} as float {f3:.20f}')
    

    Output:

    3.12.3 (tags/v3.12.3:f6650f9, Apr  9 2024, 14:05:25) [MSC v.1938 64 bit (AMD64)]
    2476979795053773/2251799813685248 as float 1.10000000000000008882
    11/10 as float 1.10000000000000000000
    11/10 as float 1.10000000000000000000