Diszkrét matematika 3. előadás Sapientia Egyetem, Műszaki és Humántudományok Tanszék Marosvásárhely, Románia mgyongyi@ms.sapientia.ro 2016, őszi félév
Miről volt szó az elmúlt előadáson? A gyorshatványozás algoritmusa - iteratív, rekurzív változatok. Számtartományok: racionális számok, irracionális számok Racionális számok sorozatba rendezése legnagyobb közös osztó algoritmusa, rekurzív változat Lánctörtek racionális számok lánctört jegyei
Miről lesz szó? Számtartományok: valós számok, komplex számok racionális számok lánctört jegyei valós számok lánctört jegyei híresebb irracionális számok számjegyeinek a kigenerálása k-ik gyök meghatározása: Newton módszerrel logaritmus maghatározása másodfokú egyenlet komplex gyökei fraktálok: Mandelbrot, Julia
Lánctörtek (Continued fraction) A lánctört egy emeletes tört, amely kétféle alakban is megadható, ahol a két alak átalakítható egymásba: a 0 + a 1 + b 1 b 2 b3 a 2 + a 3 +... d 0 + d 1 + 1 d 2 + 1 1 d 3 +... A második alak esetében a [d 0, d 1, d 2, d 3,... ] számsorozatot a lánctört jegyeinek hívják. Megállapíthajuk, hogy: a racionális számok véges lánctörtek, az irracionális számok végtelen lánctörtek.
Algoritmusok Pythonban 1. feladat: határozzuk meg az x y def lanct(x, y): L = [] while 1: L += [x / y] r = x % y if r == 0: break x = y y = r return L racionális számnak megfelelő lánctört jegyeit >>> lanct(89, 63) [1, 2, 2, 2, 1, 3] >>> lanct(89, 55) [1, 1, 1, 1, 1, 1, 1, 1, 2]
Algoritmusok Pythonban 2. feladat: határozzuk meg az x y átírjuk a maradékos osztást!! def lanct1(x, y): L = [] while 1: temp = x / y L += [temp] r = x - temp * y if r == 0: break x = y y = r return L racionális számnak megfelelő lánctört jegyeit, >>> lanct(61, 47) [1, 3, 2, 1, 4]
Valós számok a racionális és irracionális számok halmaza halmazjelölés: R = Q Q, egy szám egyszerre nem lehet racionális és irracionális is, a valós számokhoz hozzárendelhető, egy mindkét irányban végtelen egyenes egy-egy pontja, kommutatívitás, asszociatívítás, disztributívítás, az egész számokkal ellentétben a valós számok halmaza nem megszámlálható, a számítástechnikában nem valós mennyiségekkel dolgozunk, ezek egy közeĺıtő értéke lesz eltárolva: lebegőpontos ábrázolás,
Valós számok A valós számok halmaza nem megszámlálható: feltételezzük, az ellenkezőjét, ha a valós számok halmaza megszámlálható lenne, akkor, a 0 és 1 közötti valós számok halmaza is megszámlálható lenne, létezik egy számsorozat, amelyet a 0 és 1 közötti valós számok alkotnak : r 1, r 2,..., r n,..., alkalmazzuk a következő ábrázolási módot: r 1 = 0.d 11d 12d 13d 14... r 2 = 0.d 21d 22d 23d 24... r 3 = 0.d 31d 32d 33d 34... r 4 = 0.d 41d 42d 43d 44.... ahol d ij {0, 1, 2,..., 9} ekkor az r = 0.d 1d 2d 3d 4... egy új valós szám lesz, { amely nem szerepel a 4 ha dii 4, fenti szabály szerint megadott listában, ahol d i = 5 ha d ii = 4.
Valós számok Példa: r 1 = 0.3567842... r 2 = 0.2146577... r 3 = 0.8945678... r 4 = 0.3452109.... A listában nem szereplő valós szám: 0.4454..., mert d 11 4, d 22 4, d 33 = 4, d 44 4,....
Algoritmusok Pythonban 3. feladat: határozzuk meg az a valós számnak megfelelő lánctört jegyeit from math import floor def lanctreal(a, prec): temp = floor(a) L = [int(temp)] i = 0 while i < prec and a!= temp: a = 1.0 / (a - temp) temp = floor(a) L += [int (temp)] i += 1 return L >>> lanctreal(61/47.0, 5) [1, 3, 2, 1, 3, 1]
Algoritmusok Pythonban 3. feladat: >>> import math >>> lanctreal(math.sqrt(2), 10) [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] >>> lanctreal(math.sqrt(6), 10) [2, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4] >>> lanctreal(math.pi, 15) [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3, 3, 23] >>> lanctreal(math.e, 15) [2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1]
Python sintaxis A Decimal típus: a Decimal típus a decimal modulban van definiálva, a felhasználó által óhajtott pontossággal ábrázolja a lebegőpontos (valós) számokat, a getcontext.prec() segítségével a tizedes jegyek számát adhatjuk meg, Az int, a float, a string típusokból egyaránt létre lehet hozni Decimal típusú értéket. >>> 0.1 + 0.1-0.2 0.0 >>> 0.1 + 0.1 + 0.1-0.3 5.551115123125783e-17
Python sintaxis >>> Decimal(0.1) Decimal( 0.1000000000000000055511151231257827021181583404541015625 ) >>> Decimal( 0.1 ) Decimal( 0.1 ) >>> Decimal( 0.1 ) + Decimal( 0.1 ) + Decimal( 0.1 ) - Decimal( 0.3 ) Decimal( 0.0 )
Algoritmusok Pythonban 4. feladat: a n érték meghatározása lánctörtek segítségével A kiinduló képlet a következő, ahol a értéke egy akármilyen szám: ha a = 1, akkor: n = 1 + 2 + n = a + n a 2 2 + n 1 n 1 a+ n n 1 2 + n 1 2 +...
Algoritmusok Pythonban 5. feladat: a 2 értékének meghatározása lánctörtek segítségével: 2 = 1 + 1 2 + 1 2 + 1 2 +... from decimal import Decimal, getcontext def lanct_sqrt(): p = 500 getcontext().prec = 30 # 30 szamjegy temp = Decimal(0) for x in range (0, p): temp = 1 / (2 + temp) return 1 + temp >>> lanct_sqrt() Decimal( 1.41421356237309504880168872421 )
A π szám a kör kerületének és átmérőjének hányadosa az eukleidészi geometriában más definíciók is léteznek, melyek kihagyják a kört irracionális és transzcendens szám (nincs olyan egész együtthatós polinom amelynek gyöke lenne) 6. feladat: a π értékének meghatározása lánctörtek segítségével π = 1 + 3 + 4 1 2 2 2 5 + 32 7 +... π = 3 + 6 + 6 + 1 3 2 5 2 6 + 72 6 +...
A π szám def lanct_pi(): p = 1000 getcontext().prec = 100 # 100 szamjegy temp = Decimal(0) for x in range (p + 1, 0, -1): a = x * x b = 2 * x + 1 temp = a / (b + temp) return 4 / (1 + temp) >>> lanct_pi() Decimal( 3.1415926535897932384626433832795028841971693993751058209 74944592307816406286208998628034825342117067 )
Az e szám irracionális és transzcendens szám többféleképpen lehet értelmezni: ( e = lim 1 + 1 ) n. n n Az e értékének meghatározása lánctörtek segítségével: e = 2 + 1 + 2 + 1 1 2 3 + 3 4 +...
Algoritmusok Pythonban 7. feladat: a log e z értékének meghatározása lánctörtek segítségével log(1 + z) = 1 + def lanct_log(z, p, szj): z -= 1 getcontext().prec = szj temp = Decimal(0) for x in range (p, 0, -1): t = (x + 1) / 2 a = x + 1 b = t * t * z temp = b / (a + temp) return z / (1 + temp) 2 + 3 + z 1 2 z 4 + 1 2 z 2 2 z 2 2 z 5 + 32 z 6 +...
Algoritmusok Pythonban 7. feladat: >>> lanct_log(2, 500, 20) Decimal( 0.69314718055994530940 ) >>> import math >>> math.log(2) 0.6931471805599453 >>> lanct_log(decimal(math.e), 1000, 20) Decimal( 0.99999999999999994681 ) >>> math.log(math.e) 1.0
Algoritmusok Pythonban 8. feladat: a sin(z) értékének meghatározása lánctörtek segítségével z sin(z) = z 2 1 + 2 3 z 2 2 3 z 2 + 4 5 z 2 4 5 z 2 + 6 7 z 2 +... def lanct_sin(z): p = 300 getcontext().prec = 50 temp = Decimal(0) for x in range (2*p, 0, -2): a = (x+2) * (x+3) - z*z b = x * (x+1) * z * z temp = b / (a + temp) temp = z*z / (2*3-z*z + temp) return z / (1 + temp)
Algoritmusok Pythonban 8. feladat: >>> lanct_sin(60) Decimal( -0.30481062110221670562576204186131345751440565822218 ) >>> import math >>> math.sin(60) -0.3048106211022167 >>> math.sqrt(3)/2 0.8660254037844386 >>> math.sin(60 * math.pi/180) 0.8660254037844386
Algoritmusok Pythonban 8. feladat: def lanct_sinr(z): p = 300 getcontext().prec = 50 z = Decimal(z * math.pi/180) temp = Decimal(0) for x in range (2*p, 0, -2): a = (x+2) * (x+3) - z*z b = x * (x+1) * z * z temp = b / (a + temp) temp = z*z / (2*3-z*z + temp) return z / (1 + temp) #atalakitjuk a szoget radianna >>> lanct_sinr(60) Decimal( 0.86602540378443858934550903079182617193526553351420 )
Aranymetszés, aranyarány (Golden Ratio), a ϕ szám két mennyiség, a, b, a > b az aranymetszés szerint aránylik egymáshoz, ha fennáll: a b = a + b def = ϕ a a ϕ meghatározása érdekében feĺırhatjuk: a + b a = 1 + 1 a, azaz fennáll: b ϕ = 1 + 1 ϕ ϕ2 = ϕ + 1 megoldva a fenti egyenletet kapjuk, hogy ϕ = 1 + 5 2 a ϕ irracionális szám = 1.61803... és ˆϕ = 1 5 2 = 0.61803...
Aranymetszés, aranyarány (Golden Ratio), a ϕ szám építészet: Parthenon homlokzatának arányértékei: logok: Toyota, Mercedesz, stb. Pentagramma (szabályos ötszög): természet: napraforgó spirlajai piros zold = zold kek = kek lila = ϕ
Aranymetszés, aranyarány (Golden Ratio), a ϕ szám Kiindulva az alábbi összefüggésből: ϕ = 1 + 1, lánctörtek segítségével is ϕ feĺırhatjuk a ϕ értékét: ϕ = 1 + 1 + 1 + 1 1 1 1 + 1...
Algoritmusok Pythonban 9. feladat: gyökvonás, a k-ik gyök meghatározása, Newton féle módszer alapján k n meghatározása: xi+1 = 1 [ (k 1) x i + n ], ahol x k x k 1 0 = 1 egy i kezdeti érték. ha k = 2, akkor a négyzetgyök meghatározásának képlete: x i+1 = 1 (x 2 i + n ) x i a beépített operátorral: >>> 10 ** 0.5 3.1622776601683795 >>> from decimal import Decimal, getcontext >>> getcontext().prec = 100 >>> 10 ** Decimal( 0.5 ) Decimal( 3.16227766016837933199889354443271853371955513932521682685... )
Algoritmusok Pythonban 10. feladat: négyzetgyökvonás x i+1 = 1 (x 2 i + n ) x i x 0 = 1 from decimal import Decimal, getcontext def my_sqrt(n): getcontext().prec = 100 n = Decimal(n) x0 = 1 while True: xi = (x0 + n/x0)/2 if xi == x0: return xi x0 = xi
Algoritmusok Pythonban 11. feladat: természetes alapú logaritmus meghatározása. Használható összefüggések: ln (x) = (x 1) (x 1)2 2 ln (x) = lim n n (x 1/n 1) + (x 1)3 3 (x 1)4 4 = ( 1) n+1 (x 1) n n n=1 def ln(x): n = 100000000.0 return n * ((x ** (1/n)) - 1)
Komplex számok A komplex számok a valós számhalmaz egy olyan bővítése, melyben negatív számok esetén is értelmezett a gyökvonás. halmazjelölés: C, és három modell alapján is értelmezhető: halmazelméleti, geometriai, algebrai modellek halmazelméleti modell: C = {(a, b) a R, b R}, azaz a számhalmazt rendezett számpárok alkotják, ahol az elemek valós számok, imaginárius rész: az a komplex szám amelynek négyzete -1, jele az i a komplex számok a + bi alakban írhatóak fel, ahol a valós rész, b az imarinárius rész ha b = 0, akkor valós számot kapunk a valós számok körében megismert műveleti tulajdonságok megmaradnak additív semleges elem: z = 0 + 0i multiplikatív semleges elem: z = 1 + 0i additív inverz elem: z = a bi, multiplikatív inverz elem: 1/z = a/(a 2 + b 2 ) b/(a 2 + b 2 )i, z 0
Műveletek komplex számokkal Műveleti szabályok: a = a 1 + a 2i abs(a) = a1 2 + a2 2 b = b 1 + b 2i a + b = (a 1 + b 1) + (a 2 + b 2)i a b = (a 1 + b 1) (a 2 + b 2)i a b = (a 1 b 1 a 2 b 2) + (a 2 b 1 + a 1 b 2)i 1 b 1 = b (b1 2 + b2 2 ) b 2 (b1 2 + b2 2 ) i a b = a 1 b (1)
Komplex számok Pythonban >>> a = complex(2, 4) >>> a.imag 4.0 >>> a.real 2.0 >>> abs(a) 4.47213595499958 >>> b = complex(1,10) >>> a + b (3 + 14j) >>> a - b (1-6j) >>> a * b (-38 + 24j) >>> a / b (0.4158415841584159-0.15841584158415842j)
Algoritmusok Pythonban 12. feladat: Határozzuk meg egy másodfokú egyenlet gyökeit def megyenlet2 (a, b, c): if a == 0: return egyenlet(b, c) delta = b*b - 4*a*c if delta < 0: valosr = -b / (2*a) imagr = math.sqrt( abs (delta)) / (2 * a) gy1 = complex(valosr, imagr) gy2 = complex(valosr, -imagr) return (gy1, gy2) if delta == 0: gy = -b/(2*a) return (gy, gy) if delta > 0: gy1 = (-b + math.sqrt(delta)) / (2*a) gy2 = (-b - math.sqrt(delta)) / (2*a) return ( gy1, gy2 )
Mandelbrot fraktál Fraktálok: kiindulva egy komplex számból, egy iterációs folyamat eredményeként a képernyőre kirajzolt pontok fraktál alakzatokat hozhatnak létre minél nagyobb az iteráció szám, annál jobb a kirajzolt kép minősége a Mandelbrot halmaz iterációs képlete: z n+1 = (z n) 2 + c, ahol a kezdeti z 0 értéket és a c értéket a programozó álĺıtja be a Mandelbrot halmaz azokat a c komplex számokat fogja tartalmazni, amelyekre a z n sorozat nem tart a végtelenbe, és z 0 = 0 a z n sorozat a végtelenbe tart, ha az abszolútértéke nagyobb lesz mint 2.
Algoritmusok Pythonban 13. feladat: Határozzuk meg a Mandelbrot halmaz elemeit. Egy halmazbeli elem esetén rajzoljunk #-t a képernyőre, másképp space-t. def fman(): L1 = [a*0.07 for a in range (-15, 16)] L2 = [a*0.04 for a in range (-50, 26)] for y in L1: L = "" for x in L2: z = 0 c = complex(x, y) for i in range (40): z = z ** 2 + c if abs(z) > 2: L += " " break if abs(z) <= 2: L += "#" print L
Julia fraktál 14. feladat: Határozzuk meg a Julia halmaz elemeit. A Julia halmaz iterációs képlete ugyanaz, mint a Mandelbrot halmazé, azzal a különbséggel, hogy a c értéke itt konstans, legyen c = 1 0.25i def fjulia(): L1 = [a*0.07 for a in range (-15, 16)] L2 = [a*0.04 for a in range (-40, 36)] c = complex (-1, -0.25) for y in L1: L = "" for x in L2: z = complex(x, y) for i in range (40): z = z ** 2 + c if abs(z) > 2: L += " " break if abs(z) <= 2: L += "#" print L
Megjegyzések az L1, L2 intervallumokat módosíthatjuk, a kirajzolt alakzat nagyobb lesz: L1 = [a*0.05 for a in range (-20, 21)] L2 = [a*0.02 for a in range (-80, 31)] a grafikus megjelenítéshez használjuk a pygmae csomagot (lehet mást is): http://www.pygame.org/download.shtml a grafikus megjelenítés forrása: http://fractalart.gallery/mandelbrot-set-in-python-pygame
Mandelbrot fraktál, grafikus megjelenítés from pygame.locals import * import pygame def mainma(): width, height = 800, 800 screen = pygame.display.set_mode((width,height),doublebuf) xaxis = width/1.5 yaxis = height/2 scale = 200.0 iterations = 40 for iy in range(height/2+1): for ix in range(width): z = 0 c = complex((ix - xaxis)/scale, (iy - yaxis)/scale)
Mandelbrot fraktál, grafikus megjelenítés for i in range(iterations): z = z**2 + c if abs(z) > 2: v = 765*i/iterations if v > 510: color = (255, 255, v%255) elif v > 255: color = (255, v%255, 0) else: color = (v%255, 0, 0) break if abs(z) <= 2: color = (0, 0, 0) #end for screen.set_at((ix, iy), color) screen.set_at((ix, height-iy), color) #end for, for
Mandelbrot fraktál, grafikus megjelenítés pygame.display.update() while True: event = pygame.event.poll() if (event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE)): break #end def mainma() pygame.quit()
Mandelbrot fraktál
Julia fraktál, grafikus megjelenítés from pygame.locals import * import pygame def mainju(): width, height = 800,1000 #width, height = 320, 320 screen = pygame.display.set_mode((width,height),doublebuf) xaxis = width/2.0 yaxis = height/3.7 scale = 170.0 iterations = 40 c = complex (-0.824, -0.17711) for iy in range(height/2 + 1): for ix in range(width): z = complex((ix - xaxis)/scale, (iy-yaxis)/scale) for i in range(iterations): z = z**2 + c if abs(z) > 2.0: color = (i % 8 * 32, i % 16 * 16, i % 32 * 8) break
Julia fraktál, grafikus megjelenítés if abs(z) <= 2: color = (0, 0, 0) screen.set_at((ix, iy), color) screen.set_at((width, height), color) #end for, for pygame.display.update() while True: event = pygame.event.poll() if (event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE)): break #end def mainju() pygame.quit()
Julia fraktál c = complex (-0.824, -0.17711)
Julia fraktál További c értékek a Julia fraktálhoz: c = complex (0.285, 0.013) c = complex (-0.295, -0.55) c = complex (-0.63, -0.407) c = complex (-0.624, 0.435) c = complex (-1, -0.25) c = complex (-1, -0)