Farklı bir bölme algoritması

Denediğim kadarıyla sorunsuz çalışıyor, belki negatif sayılarda iscyclic ve cyclic_number_count doğru çalışmıyor olabilir:

class KesirliSayı():

    def __init__(self, pay, payda = 1):
        assert isinstance(pay, int) and isinstance(payda, int), "Pay ve payda tam sayı olmalıdır."
        assert payda != 0, "Payda 0 olamaz."
        self.pay = pay
        self.payda = payda

    def __float__(self):
        return self.pay / self.payda

    def __int__(self):
        return self.pay // self.payda

    def __complex__(self):
        return complex(self.pay / self.payda)

    def __abs__(self):
        return KesirliSayı(abs(self.pay), abs(self.payda))

    def __bool__(self):
        return bool(self.pay / self.payda)
        
    ### some useful methods
    def copy(self):
        return KesirliSayı(self.pay, self.payda)
    
    def ispositive(self):
        return not self.isnegative()

    def isnegative(self):
        p = self.pay < 0
        q = self.payda < 0
        return (q or p) and not (q and p)
        
    def isinteger(self):
        return self.pay // self.payda == self.pay / self.payda

    def iscyclic(self):
        return bool(self.cyclic_number_count())

    def cyclic_number_count(self):
        tam, kesirli = self.pay // self.payda, self.pay % self.payda
        bölen = self.payda

        kalanlar = [kesirli]
        kalanlar_kümesi = {kesirli}

        devirli, v = 0, 0
        while True:
            kesirli *= 10
            bölüm, kalan = kesirli // bölen, kesirli % bölen

            v += 1
            
            if kalan == 0:
                break
            
            if kalan in kalanlar_kümesi:
                devirli = v - kalanlar.index(kalan)
                break

            kalanlar.append(kalan)
            kalanlar_kümesi.add(kalan)

        return devirli
        

    def __repr__(self):
        if self.isnegative():
            önek = "-"
            a = abs(self)
            pay, payda = a.pay, a.payda
        else:
            önek = ""
            pay, payda = self.pay, self.payda

        tam, kesirli = pay // payda, pay % payda
        bölen = payda

        kalanlar = [kesirli]

        devirli = 0
        virgülden_sonra = ""
        while True:
            kesirli *= 10
            bölüm, kalan = kesirli // bölen, kesirli % bölen

            virgülden_sonra += str(bölüm)
            
            if kalan == 0:
                break
            
            if kalan in kalanlar:
                devirli = len(virgülden_sonra) - kalanlar.index(kalan)
                break
                
            kalanlar.append(kalan)
            kesirli = kalan
    
##        print(f"Virgülden sonraki son {devirli} sayı devirli.")
        
        tam = önek + str(tam)

        if devirli:
            üst_çizgi = " " * (len(tam) + len(virgülden_sonra) - devirli + 1) + "_" * devirli
            return üst_çizgi + "\n" + tam + "." + virgülden_sonra
        return tam + "." + virgülden_sonra

def test():
    assert repr(KesirliSayı(132, 13)) == "   ______\n10.153846"
    assert repr(KesirliSayı(1, 99)) == "  __\n0.01"
    assert repr(KesirliSayı(10, 99)) == "  __\n0.10"
    assert repr(KesirliSayı(12313, 123)) == "    _____\n100.10569"
    assert repr(KesirliSayı(2, 9)) == "  _\n0.2"
    assert repr(KesirliSayı(21, 90)) == "   _\n0.23"
    assert repr(KesirliSayı(21, 909)) == "  ____\n0.0231"
    KesirliSayı(123, 901) # bayaa uzun bir devirli kısmı var
    assert repr(KesirliSayı(5, 100)) == "0.05"
    assert repr(KesirliSayı(3, 4)) == "0.75"
    assert repr(KesirliSayı(10, 4)) == "2.5"
    assert repr(KesirliSayı(10123, 9)) == "     _\n1124.7"
    assert repr(KesirliSayı(3, 101)) == "  ____\n0.0297"
    assert repr(KesirliSayı(10, 2)) == "5.0"

if __name__ == "__main__":
    test()
1 Beğeni