TIL: Fun things about printing fractions.

Published July 07, 2025

For my cooklang-py project I want to store quantities in a numeric format. So if you say 1.5 cups I want to store it like that. If you say 1/2 cup I want to store it like that. The idea being that if we store the quantities in a numeric format we can do math and scale the recipe.

The only problem is if you say 1 3/4 cup like I do in my Chocolate Chip Banana Muffins recipe. Some of the problem was a bug in my parsing code that converted that 13/4. Which is how I realized the problem. I updated the recipe file to be 7/4 expecting that fractions.Fraction would give me back the string 1 3/4 but it gave me 7/4. (In the end I went with 1.75 because that has no issues.)

So I've decided that I need to tweak the Fractions class to get the string I wanted. First I tried:


class MyFraction(Fraction):
    def __str__(self):
        x = self.numerator // self.denominator
        return f'{x} {abs(self) - abs(x)}'

and that works for positive fractions. But not for negative fractions. When I tried it with -7/4 I ended up with the string -2 1/4. This is because // is not integer division - it's floor division. So 7 // 4 = 1 but -7 // 4 == -2. After some fiddling I came up with this:


class MyFraction(Fraction):
    def __str__(self):
        x = abs(self.numerator) // self.denominator
        return f'{"-" if self < 0 else ""}{f"{x} " if x else ""}{abs(self) - x}'

which works as I expect:


print(MyFraction('4/5'))
4/5
print(MyFraction('-4/5'))
-4/5
print(MyFraction('-7/5'))
-1 2/5
print(MyFraction('7/5'))
1 2/5

When I was in elementary school I learned that fractions are hard. Working with them in Python can be just as hard.


Previous: Templates in Obsidian will make my life easier. Next: About antigravity