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.