I have created a fraction calculator which includes +,-,*,/. All my functions work fine except one condition in subtraction where both the values are equal. I believe it has to do with the simplify(gcd) function that I added but not sure where the problem is. Below is the code where I have kept only the subtraction function for prioritizing the problem:
Class Fraction:
def __init__(self, num, denom) -> None:
self.num = int(num / simplify(abs(num), abs(denom)))
self.denom = int(denom / simplify(abs(num), abs(denom)))
if self.denom < 0:
self.denom = abs(self.denom)
self.num = -1*self.num
elif self.denom == 0:
raise ZeroDivisionError("cansnot divide by zero")
def __sub__(self, other: "Fraction") -> "Fraction":
n: int = self.num * other.denom - self.denom * other.num
d: int = self.denom * other.denom
new = Fraction(n, d)
return (new)
def __str__(self) -> str:
if self.denom == 1:
return str(self.num)
else:
return(f"{self.num}/{self.denom}")
def simplify(num, denom):
while num != denom:
if num > denom:
num = num - denom
else:
denom = denom - num
return num
def get_fraction() -> Fraction:
"""Convert numerator and denominator to integer values"""
while True:
num: str = input("Enter the numerator")
denom: str = input("Enter the denominator")
try:
a = int(num)
b = int(denom)
return Fraction(a, b)
except ValueError:
print("Enter valid numerator and denominator")
def compute(f1: Fraction, operator: str, f2: Fraction) -> None:
okay = True
if operator == '-':
result = f1.__sub__(f2)
else:
print(operator, " is an unrecognized operator")
okay = False
if okay == True:
print(f"{f1} {operator} {f2} = {result}")
def main() -> None:
"""Main menu"""
print("Welcome to the Fraction Calculator! ")
while True:
print('Press Q to quit or any other key to start')
z = input("Start or Quit?")
if z == 'Q' or z == 'q':
exit()
else:
f1: Fraction = get_fraction()
operator: str = input("Operation (+, -, *, / , = , < , > , <= , >= , != ): ")
f2: Fraction = get_fraction()
try:
compute(f1, operator, f2)
except ZeroDivisionError as e:
print(e)
if __name__ == '__main__':
main()
Below is the output for this code, where I am having 4/5 as both the fractions, it just gives me a blank output.
Welcome to the Fraction Calculator!
Press Q to quit or any other key to start
Start or Quit? s
Enter the numerator 4
Enter the denominator 5
Operation (+, -, *, / , = , < , > , <= , >= , != ): -
Enter the numerator 4
Enter the denominator 5
All other values work fine for the sub-function except when the values are equal.
Your simplify method is a slower version of a gcd and will fall into an infinite loop when num is zero.
you could replace it with this:
from math import gcd
def simplify(num, denom):
return gcd(num,denom) if denom else 1
if you don't want to import math, you can write your own version of the gcd() function using a faster algorithm than the subtractive form you're currently using in simplify:
def gcd(a,b):
while b != 0: a,b = b,a%b
return abs(a)
Or, you could replace simplify()'s code with an actual simplification of both components that places the sign on top in one step:
def simplify(num, denom):
g = gcd(num,denom) if denom else 1
s = -1 if (num<0) != (denom<0) else 1
return int(abs(num) // g * s), int(abs(denom) // g)
and use it like this in the constructor:
self.num,self.denom = simplify(num,denom)
if you convert the string input using Decimal() (from the decimal module) instead of int(), this improved simplify() could do even cooler things such as figuring out that:
simplify(-8.5,12.5) # is (-17, 25)
For example:
from decimal import Decimal
f = input("enter a fraction as a/b or a decimal value: ")
num,denom,*_ = map(Decimal,(*f.split("/"),1))
print(simplify(num,denom))
enter a fraction as a/b or a decimal value: 0.68
(17, 25)