1    # Ok, takze dneska mame delat zlomek. Budeme na nej potrebovat funkci co zjisti
   2    # nejvetsi spolecnej delitel dvou cisel. Je to funkce, protoze nijak nesouvisi
   3    # s tim zlomkem (krome toho, ze zlomek ji potrebuje). Je to ale "uzitecnej" kus
   4    # kodu co mozna pouzijeme jeste nekdy pozdejc, a tak se nam hodi samostatne.
   5    
   6    def gcd(i,j):
   7        """ Vrati nejvetsi spolecny delitel dvou cisel. """
   8        while (True): # Opakujeme porad
   9            while (i>j): i=i-j # dokud je prvni cislo vetsi, odecitam od nej druhe
  10            while (j>i): j=j-i # a ted dokud je druhe cislo vetsi, odecitam od nej prvni
  11            if (i==j): break # kdyz se cisla rovnaji, tak jsem skoncil, a mam vysledek, jinak opakuju cyklus
  12        return i # vratim to cislo
  13    
  14    # A ted uz vlastni trida zlomku. Obecne pro vsechny tridy plati cim vic prace si
  15    # date s tridou jako takovou, tim jednoduzsi je pak vlastni prace s ni, jak
  16    # muzete videt na demonstracnim programu dole.
  17    
  18    
  19    
  20    # trida zacina klicovym slovem class, nazvem tridy a dvojteckou. Vsechny prvky tridy
  21    # jsou odsazeny, aby se vedelo ze patri k tride.
  22    class Zlomek:
  23        """ Trida co se chova jako zlomek, umi zakladni aritmeticky operace. """
  24        _citatel = 0 # citatel (privatni jen z metod dostupna promenna)
  25        _jmenovatel = 1 # jmenovatel zlomku (takytak)
  26    
  27        
  28        # privatni funkce, takze ji muzou volat jen ostatni metody zlomku, a ne nikdo
  29        # z venci (protoze volat ji z venci by bylo zbytecny). Spravnej zlomek je vzdycky
  30        # zkracenej
  31        def _zkrat(self):
  32            """ Zkrati zlomek, pokud je treba. """
  33            d=gcd(self._citatel,self._jmenovatel) # najdu si gcd citatele a jmenovatele
  34            self._citatel=self._citatel/d # vydelim s nim citatel
  35            self._jmenovatel=self._jmenovatel/d # vydelim s nim jmenovatel
  36    
  37        # konstruktor zlomku. Nastavi citatel a jmenovatel. Jmenovatel je implicitne 1
  38        # abych mohl inicializovat zlomek jednoduse na cela cisla. 
  39        def __init__(self,c,j=1):
  40            """ Vytvori novy zlomek a nastavi citatel a jmenovatel. """
  41            self.setCitatel(c) # k nastaveni pouzijeme settery, nejdriv citatele 
  42            self.setJmenovatel(j) # a pak i jmenovatele
  43    
  44        # getter - tedy metoda ktera z venci zpristupnuje privatni polozky objektu,
  45        # momentalne citatel
  46        def citatel(self):
  47            """ Vrati citatel zlomku. """
  48            return self._citatel
  49          
  50        # getter pro jmenovatel
  51        def jmenovatel(self):
  52            """ Vrati jmenovatel zlomku. """
  53            return self._jmenovatel
  54    
  55        # setter - metoda co naopak nastavuje privatni data objektu. Protoze to je
  56        # jedina sance jak nastavit objektu jeho vlastnosti, ma tak objekt plnou
  57        # kontrolu nad tim, jaka data se do nej dostanou, coz je dulezite pro to,
  58        # abychom mohli zarucit ze v objektu budou vzdycky smysluplna data.
  59        def setCitatel(self,value):
  60            """ Nastavi citatele zlomku tak, aby byl zlomek ve spravnem tvaru. """
  61            if (value<0): # kdyz ma byt citatel zaporny
  62                self._jmenovatel=-self._jmenovatel # tak zmenime znamenko jmenovateli
  63                value=-value # a novy citatel bude kladny (ve zlomku muze byt jen jmenovatel zaporny a urcuje znamenko celeho zl
        omku)
  64            self._citatel=value # nastavime hodnotu noveho citatele
  65            if (value==0): # pokud je citatel nula, 
  66                self._jmenovatel=1 # nastavime jmenovatel na 1, aby byly vsechny nuly vzdycky 0/1 a ne treba 0/4
  67            self._zkrat() # nakonec je treba zlomek zkratit
  68    
  69        # nastavime jmenovatel. Je treba dat pozor akorat na nulu, ktera ve jmenovateli byt nesmi.
  70        def setJmenovatel(self,value):
  71            """ Nastavi jmenovatel, pokud by mel byt nula, nic se neprovede. """
  72            if (value!=0): # jestlize je nova hodnota jina nez 0
  73                self._jmenovatel=value # provede nastaveni
  74                self._zkrat() # a zkrati se zase
  75    
  76        # funkce co vrati hodnotu zlomku jako desetinny cislo, abychom ji mohli pouzit dal
  77        def __float__(self):
  78            """ Vrati svoji hodnotu jako float. """
  79            return (self._citatel*1.0)/self._jmenovatel # * 1.0 abych udelal desetinne cislo do deleni
  80    
  81        # specielni funkce co vrati retezec co reprezentuje zlomek.
  82        def __str__(self):
  83            """ Vrati zlomek jako retezec, napriklad (2/3). """
  84            return "("+str(self._citatel)+"/"+str(self._jmenovatel)+")"
  85    
  86        # specielni porovnavaci funkce. Vrati 1 kdyz je levy zlomek vetsi nez pravy,
  87        # -1 kdyz je levy mensi nez pravy a 0 kdyz jsou oba dva zlomky stejne. 
  88        def __cmp__(self,other):
  89            """ Porovna dva zlomky. """
  90            if (self._citatel*other._jmenovatel<other._citatel*self._jmenovatel):
  91                return -1 # klasicky porovnavani (vychazi ze vzorce pro scitani zlomku)
  92            if (self._citatel!=other._citatel):
  93                return 1 # ted kdyz nejsou stejny, tak je levej vetsi
  94            if (self._jmenovatel!=other._jmenovatel):
  95                return 1 # to samy
  96            return 0 # kdyz jsme se dostali az sem, musi byt stejny...
  97    
  98    
  99        # a konecne funkce co umi scitat zlomek se zlomkem. Je to opet specialni funkce,
 100        # ktera vrati novej zlomek. Zlomek scita podle pravidla
 101        # a/b+c/d = (ad+cb)/bd
 102        def __add__(self,other):
 103            """ Secte dva zlomky a vrati vysledek. """
 104            return Zlomek(self._citatel*other._jmenovatel+other._citatel*self._jmenovatel, self._jmenovatel*other._jmenovatel)
 105    
 106        # domaci ukol: udelejte nasledujici funkce pro odcitani, nasobeni a deleni:
 107        
 108        def __sub__(self,other):
 109            """ Odecte od sebe dva zlomky (self-other) a vrati vysledek. """
 110            pass
 111    
 112        def __mul__(self,other):
 113            """ Vynasobi dva zlomky a vrati vysledny zlomek. """
 114            pass
 115    
 116        def __div__(self,other):
 117            """ Vydeli self/other a vrati vysledny zlomek. """
 118            pass
 119            
 120    # tohle je konec definice tridy, vracime se na zakladni odsazeni a muzeme si ukazat
 121    # jak se takovej zlomek pouzije: Je to vazne jednoduchy
 122    
 123    z1=Zlomek(3,4) # z1 je 3/4
 124    z2=Zlomek(6) # z2 je 6 (6/1)
 125    print z1+z2 # napise kolik je 3/4 + 6 jako zlomek
 126    # atd...