#!/usr/bin/python # -*- coding: utf-8 -*- """Una implementación de números rationales. Hecho para mostrar un ejemplo de TDD. Duplica un módulo en la librería estándar. >>> frac(3, 4) 3/4 >>> frac(1, 2) + frac(1, 3) 5/6 >>> frac(1, 3) + frac(1, 2) 5/6 >>> frac(1, 3) + frac(1, 3) 2/3 >>> frac(1, 2) + 1 3/2 >>> frac(7, 6) - 1 1/6 >>> frac(7, 6) - frac(1, 3) 5/6 >>> frac(7, 4) % frac(1, 2) 1/4 >>> frac(9, 2) % 2 1/2 >>> frac(1, 2) == frac(1, 2) True >>> frac(2, 3) == frac(1, 3) False >>> frac(1, 2) == frac(1, 3) False >>> frac(1, 3) == frac(3, 9) True >>> frac(0, 3) == 0 True >>> frac(0, 3) != 0 False >>> gcd(frac(1, 3), frac(1, 2)) 1/6 """ import doctest import decimal def gcd(a, b): """Te devuelve el divisor más grande común de a y b. Por ejemplo: >>> gcd(6, 9) 3 >>> gcd(8, 4) 4 >>> gcd(7, 8) 1 """ while b != 0: a, b = b, a % b return a def to_frac(x): if isinstance(x, int): return frac(x, 1) elif isinstance(x, decimal.Decimal): return frac(int(x), 1) else: return x class frac: def __init__(self, num, denom): factor = gcd(num, denom) self.num = num / factor self.denom = denom / factor def __repr__(self): return '%s/%s' % (self.num, self.denom) def __add__(self, otro): otro = to_frac(otro) denom_comun = otro.denom * self.denom return frac( self.num * otro.denom + otro.num * self.denom, denom_comun) def __sub__(self, otro): return self + -otro def __neg__(self): return frac(-self.num, self.denom) def __mod__(self, otro): otro = to_frac(otro) denom_comun = otro.denom * self.denom num_cvt = self.num * otro.denom otro_num_cvt = otro.num * self.denom return frac(num_cvt % otro_num_cvt, denom_comun) def __eq__(self, otro): otro = to_frac(otro) return self.num * otro.denom == otro.num * self.denom def __ne__(self, otro): return not (self == otro) if __name__ == '__main__': doctest.testmod()