python中的分数分割不正确

时间:2014-07-16 21:18:05

标签: python python-3.x fractions

我正在做tutorial on algorithms

其中一个练习是创建一个分数类,它可以采用负分母并仍能正确显示结果。然而,当我分开时,我仍然得到负输出:

class Fraction:
    def __init__(self, num, denom):
        if isinstance(num, int) or isinstance(denom, int):
            common = gcd(num, abs(denom))
            self._num = num//common
            self._denom = abs(denom)//common
        else:
            raise TypeError

    def __str__(self):
        return "%d / %d" % (self._num, self._denom)

    def __mul__(self, other):
        denum = self._num * other._num
        div = self._denom * other._denom
        return Fraction(denum, div)

    def __truediv__(self, other):
        temp_fraction = Fraction(other._denom, other._num)
        return self.__mul__(temp_fraction)

def gcd(a, b):
    while(b):
        a, b = b, a%b
    return a

if __name__ == '__main__':
    print(Fraction(-4, -5) / Fraction(-1, -2)) 
    print(Fraction(-4, 5) / Fraction(-1, 2))
    # Both output -8 / 5, should be 8 / 5

有人能告诉我我做错了吗?

编辑我已经纠正了我的代码,并在我的doctest中重写了一些错误的断言。现在所有测试都通过了!

完整代码:

from fractions import gcd

class Fraction:
    """
    Checking if instantiating a fraction works
    >>> print(Fraction(1, 2))
    1 / 2
    >>> print(Fraction(-1, 2))
    -1 / 2
    >>> print(Fraction('Foo', 'Bar'))
    Traceback (most recent call last):
    TypeError

    Adding a fraction to another fraction
    >>> print(Fraction(1, 2) + Fraction(1, 4))
    3 / 4
    >>> print(Fraction(-1, 2) + Fraction(2, 2))
    1 / 2
    >>> print(Fraction(-1, 5) + Fraction(-1, 5))
    -2 / 5
    >>> print(Fraction(-1, -5) + Fraction(-1, -5))
    2 / 5

    Substracting a fraction from another
    >>> print(Fraction(3, 4) - Fraction(1, 4))
    1 / 2
    >>> print(Fraction(-1, 2) - Fraction(1, 4))
    -3 / 4
    >>> print(Fraction(-2, 10) - Fraction(-1, 10))
    -1 / 10
    >>> print(Fraction(-2, -10) - Fraction(-1, -10))
    1 / 10

    Multiplying 2 fractions
    >>> print(Fraction(1, 5) * Fraction(1, 2))
    1 / 10
    >>> print(Fraction(-1, 2) * Fraction(1, 4))
    -1 / 8
    >>> print(Fraction(-1, 2) * Fraction(-1, 8))
    1 / 16
    >>> print(Fraction(-1, -2) * Fraction(-1, -8))
    1 / 16

    Dividing 2 fractions
    >>> print(Fraction(1, 4) / Fraction(1, 2))
    1 / 2
    >>> print(Fraction(-1, 2) / Fraction(1, 15))
    -15 / 2
    >>> print(Fraction(-4, 5) / Fraction(-1, 2))
    8 / 5
    >>> print(Fraction(-4, -5) / Fraction(-1, -2))
    8 / 5

    Equality between fractions
    >>> print(Fraction(1, 2) == Fraction(2, 4))
    True
    >>> print(Fraction(1, 2) == Fraction(1, 3))
    False
    >>> print(Fraction(-2, 4) == Fraction(-1, 2))
    True
    >>> print(Fraction(-2, -4) == Fraction(-1, -2))
    True

    Non-equality between fractions
    >>> print(Fraction(1, 2) != Fraction(64, 128))
    False
    >>> print(Fraction(1, 4) != Fraction(999, 4000))
    True
    >>> print(Fraction(-3, 4) != Fraction(-3, 5))
    True
    >>> print(Fraction(-3, -4) != Fraction(-3, -5))
    True

    Larger size difference between fractions
    >>> print(Fraction(1, 2) > Fraction(857, 1713))
    False
    >>> print(Fraction(1, 2) > Fraction(857, 1715))
    True
    >>> print(Fraction(1, 338) >= Fraction(2, 676))
    True
    >>> print(Fraction(-2, 5) > Fraction(-1, 5))
    False
    >>> print(Fraction(-2, -5) > Fraction(-1, -5))
    True

    Smaller size difference between fractions
    >>> print(Fraction(1, 2) < Fraction(857, 1713))
    True
    >>> print(Fraction(1, 2) < Fraction(857, 1715))
    False
    >>> print(Fraction(1, 338) <= Fraction(2, 676))
    True
    >>> print(Fraction(-3, 7) < Fraction(-6, 7))
    False
    >>> print(Fraction(-3, -7) < Fraction(-6, -7))
    True
    """
    def __init__(self, num, denom):
        if isinstance(num, int) and isinstance(denom, int):
            common = gcd(num, denom)
            self._num = num//common
            self._denom = denom//common
        else:
            raise TypeError

    def __str__(self):
        return "%d / %d" % (self._num, self._denom)

    def __add__(self, other):
        denum = (self._num * other.get_denom()) + (other.get_num() * self._denom)
        div = (self._denom * other.get_denom())
        return Fraction(denum, div)

    def __sub__(self, other):
        denum = (self._num * other.get_denom()) - (other.get_num() * self._denom)
        div = (self._denom * other.get_denom())
        return Fraction(denum, div)

    def __mul__(self, other):
        denum = self._num * other.get_num()
        div = self._denom * other.get_denom()
        return Fraction(denum, div)

    def __truediv__(self, other):
        temp_fraction = Fraction(other.get_denom(), other.get_num())
        return self.__mul__(temp_fraction)

    def eq_denum(self, other):
        first = self._num * other.get_denom()
        last = other.get_num() * self._denom
        return first, last

    def __eq__(self, other):
        first, last = self.eq_denum(other)
        return first == last

    def __ne__(self, other):
        first, last = self.eq_denum(other)
        return first != last

    def __gt__(self, other):
        first, last = self.eq_denum(other)
        return first > last

    def __ge__(self, other):
        first, last = self.eq_denum(other)
        return first >= last

    def __lt__(self, other):
        first, last = self.eq_denum(other)
        return first < last

    def __le__(self, other):
        first, last = self.eq_denum(other)
        return first <= last

    def get_num(self):
        return self._num

    def get_denom(self):
        return self._denom


if __name__ == '__main__':
    import doctest
    doctest.testmod()

2 个答案:

答案 0 :(得分:1)

问题不在于除法,而是在gcd中使用__init__函数的方式。

在创建分数时,您似乎只需要删除所有abs。这样,如果gcd为否定,则denom将为否定,并且您会获得所需的行为。

if isinstance(num, int) and isinstance(denom, int):
    common = gcd(num, denom)
    self._num = num//common
    self._denom = denom//common

一些例子:

                            # with abs    # without abs
print(Fraction( 4,  6))     #  2/3           2/3
print(Fraction( 4, -6))     #  2/3          -2/3
print(Fraction(-4,  6))     # -2/3          -2/3
print(Fraction(-4, -6))     # -2/3           2/3

另请注意,两个数字应该是整数,而不仅仅是其中一个(使用and)。

答案 1 :(得分:-2)

只需将 __ str __ 更改为:

return "%d / %d" % (abs(self._num), abs(self._denom))