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...