SL_esim_L1.wxm 1 / 8 1 Johdantoa 1.1 Help: example, apropos ja describe Lista olemassa olevista erillisistä esimerkeistä saadaan komennolla example(); Esimerkiksi komentoon diff liiittyviä esimerkkejä saadaan komennolla example(diff); Komento apropos("diff"); tuo listan komennoista, joiden nimen osana on diff. Komento describe(diff); tai sille vaihtoehtoinen muoto? diff; antaaa komentoon diff liitetyn käsikirjan selityksen. Komento describe(diff, inexact); tai sille vaihtoehtoinen muoto?? diff; tuo esiin valikon erilaisista käsikirjan kohdista. Käsikirjaa on wxmaxima-käyttöliittymäohjelmasta käsin kuitenkin helpompi selata Help-valikon kohdan Maxima Help avulla. 1.2 Peruslaskutoimitukset + - * / ^ (%i1) x + y*z - a^b/c; (%o1) y z + x - a b c (%i2) 1 + 2*3-4^5/6; (%o2) - 491 3 Huomio: Laskutoimitusten järjestys ei ole vasemmalta oikealle! Laskujärjestyksen määräytyminen selitetään (melko teknisesti) käsikirjan kohdassa Operators > Introduction to operators. (%i3) 1+2*3; (%o3) 7 (%i4) (1+2)*3; (%o4) 9 1.3 Tärkeät erikoismerkit
SL_esim_L1.wxm 2 / 8 ; puolipiste päättää komennon $ dollarimerkki päättää komennon % prosenttimerkki: edellisen laskun tulos, pilkku toimii erottimena. piste: desimaalipiste; vektoreiden ja matriisien tulot : kaksoispiste: arvon tallettaminen muuttujaan = yhtäsuuruusmerkki: yhtälöt := pari kaksoispiste-yhtäsuuruusmerkki määrittelee funktion ( ) kaarisulut ilmoittavat funktion argumentit; useita komentoja samalle komentoriville; laskujärjestyksen ryhmittäminen [ ] hakasulut: listat, vektorit; indeksoidut muuttujat tai funktiot; indeksi listan alkioon { } aaltosulut ilmaisevat joukkoja ' lainausmerkki estää seuraavan symbolin arvon laskemisen (vrt. differentiaaliyhtälöt) '' kahdennettu lainausmerkki (ei kaksoislainausmerkki) pakottaa symbolin arvon laskemisen " kaksoislainausmerkki: merkkijonot /* */ /* tämä on kommentti */ 1.4 Vakiot (%i5) [%e, %gamma, %phi, %pi, %i, minf, inf]; (%o5) [ %e, γ, φ, π, %i, -, ] (%i6) float(%); (%o6) [ 2.718281828459045,.5772156649015329, 1.618033988749895, 3.141592653589793, %i, -, ] 1.5 Alkeisfunktiot ("Mathematical functions", "Polynomials") exp, log (%e-kantainen eli luonnollinen; muita ei ole); trigonometriset: sin, cos, tan cot, sec, csc; arkusfunktiot: asin, acos, atan, acot, asec, acsc; hyperboliset: sinh, cosh, tanh, coth, sech, csch; areafunktiot: asinh, acosh, atanh, acoth, asech, acsch (%i7) sin(%pi/4); (%o7) 1 2 (%i8) float(%); (%o8).7071067811865475 (%i9) sin(%pi/4), numer; (%o9).7071067811865475 1.6 (%i10) cos(n*%pi); (%o10) cos π n (%i11) declare(n, integer); (%o11) done (%i12) cos(n*%pi); (%o12) - 1 n
SL_esim_L1.wxm 3 / 8 (%i13) properties(n); (%o13) [ database info, kind n, integer ] (%i14) facts(); (%o14) [ kind n, integer ] (%i15) remove(n, integer); (%o15) done 1.7 Lukuteoreettisia funktioita ("Mathematical functions", "Number theory") abs, ceiling, floor (=entier =fix), round, max (lmax listoille), min (lmin listoille), signum,! (=factorial; kertoma; määritelty myös ei-kokonaislukumuuttujille), binomial, genfact (yleistetty kertoma; laskeva ja nouseva potenssi) divide, gcd (=syt), lcm (=pyj), mod, power_mod, inv_mod, totient, ifactors, divisors, primep, next_prime, prev_prime (%i16) 3^4/5; (%o16) 81 5 (%i17) float(%); (%o17) 16.2 (%i18) floor(3^4/5); (%o18) 16 (%i19) 5*%; (%o19) 80 (%i20) ceiling(3^4/5); (%o20) 17 (%i21) 3^4=16*5+1; (%o21) 81 = 81 (%i22) mod(3^4, 5); (%o22) 1 (%i23) power_mod(3, 4, 5); (%o23) 1 1.8 Matemaattisia algoritmeja, A primep(n) testaa, onko luku n alkuluku (=jaoton luku) vai ei (pienille luvuille tämä onnistuu helposti kokeilemalla, mutta suuria lukuja varten tarvitaan "hienompia" matemaattisia menetelmiä); prev_prime(n) määrää lukua n pienemmän alkuluvun; power_mod(a, b, n) laskee luvun a^b jakojäännöksen modulo n nopeasti ja tehokkaasti (3^(42!) = 10^(6.7*10^(50)), joten luvussa 3^(42! on n.~sata oktiljoonaa numeroa): (%i24) for n:1 thru 100 do ( if primep(n) then sprint(n) ); 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 (%o24) done
SL_esim_L1.wxm 4 / 8 (%i25) p:prev_prime(5*10^42); (%o25) 4999999999999999999999999999999999999999807 (%i26) slength(string(p)); (%o26) 43 Lasketaan 3^(42!) modulo p "oikein": (%i27) power_mod(3, 42!, p); (%o27) 13838914919878223758514877971792068020425 Luvussa 3^(42!) olevien numeroiden lukumäärä (%i28) 42!*log(3)/log(10), numer; (%o28) 6.703582817910559 10 50 (%i29) 1+floor(%); (%o29) 670358281791055946579903638149144600401548259885057 Potenssiin korotuksen 3^(42!) laskemiseen tarvittava aika, jos laskettaisiin naivilla tavalla (eli 3*3*...*3 42! kpl): (%i30) %/(10^(24)*31556952), numer; (%o30) 2.124280829755218 10 19 31556952 on vuoden pituus sekunteina; 10^(24) on kuvitteellinen laskentanopeus, tässä 10^(24) laskutoimitusta sekunnissa. Y.o. tulos on siis laskenta-aika VUOSINA! (%i31) l42:42!; (%o31) 1405006117752879898543142606244511569936384000000000 (%i32) obase:2; (%o100000) 10 (%i33) s42:charlist(string(l42)); (%o100001) [ 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] (%i34) obase:10; (%o34) 10 (%i35) map(eval_string, s42); (%o35) [ 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] Potenssiinkorotukseen power_mod(3, 42!, p) tarvittavien kertolaskujen lukumäärä (kun laskeminen tehdään "oikein"): (%i36) length(%)-1 + apply("+", %)-1; (%o36) 232
SL_esim_L1.wxm 5 / 8 1.9 Matemaattisia algoritmeja, B Polynomien jako jaottomiin tekijöihin : Kun muuttujan modulus on false, lasketaan "normaalisti"; jaottomus mitataan niin, että tekijäpolynomien kertoimet ovat rationaaliset. (Tämä rajoitus voidaan poistaa kertomalla Maximalle, mitä rationaalilukujen kunnan kuntalaajennusta käytetään.) Esimekiksi x^2-4 jakautuu tekijöihin x-2 ja x+2, mutta x^2-2 on jaoton, koska sen (reaalikertoimiset) tekijät x - sqrt(2) ja x + sqrt(2) eivät ole rationaalikertoimiset. (%i37) modulus; (%o37) false (%i38) factor(x^2-4); (%o38) x - 2 x + 2 (%i39) factor(x^2-2); (%o39) x 2-2 (%i40) factor(x^8-1); (%o40) x - 1 x + 1 x 2 + 1 x 4 + 1 (%i41) factor(x^9-1); (%o41) x - 1 x 2 + x + 1 x 6 + x 3 + 1 Jos modulus saa arvon kolme, kertoimilla lasketaan modulo kolme, eli kolmen monikerrat samaistetaan nollan kanssa: 1+1=1, 1+2=3=0, 2+2=4=3+1=1. Jos muuttujan modulus arvo muutetaan samalla komentorivillä kuin itse komento, muuttujan arvon muutos vaikuttaa vain kyseisen komennon ajan: (%i42) factor(x^9-1), modulus:3; (%o42) x - 1 9 (%i43) factor(x^9-1); (%o43) x - 1 x 2 + x + 1 x 6 + x 3 + 1 Jos muuttujan modulus arvo muutetaan omalla komentorivillään, muuttujan arvon muutos vaikuttaa niin kauan kunnes sen arvoa muutetaan uudestaan: (%i44) modulus:3; (%o44) 3 (%i45) factor(x^8-1); (%o45) x - 1 x + 1 x 2 + 1 x 2 - x - 1 x 2 + x - 1 (%i46) factor(x^9-1); (%o46) x - 1 9 (%i47) modulus:false$ (%i48) factor(x^9-1); (%o48) x - 1 x 2 + x + 1 x 6 + x 3 + 1 1.10 Riittääkö 16 numeron tarkkuus, A?
SL_esim_L1.wxm 6 / 8 (%i49) kill(values); (%o49) done Lausekeet (%i50) l_a:u*v*w*x*y; (%o50) u v w x y (%i51) [l_b1:(u*v*w)^(1/3), l_b2:(v*w*x)^(1/3), l_b3:(w*x*y)^(1/3), l_b4:(u*x*y)^(1/3), l_b5: (u*v*y)^(1/3)]; (%o51) [ u 1/ 3 v 1/ 3 w 1/ 3, v 1/ 3 w 1/ 3 x 1/ 3, w 1/ 3 x 1/ 3 y 1/ 3, u 1/ 3 x 1/ 3 y 1/ 3, u 1/ 3 v 1/ 3 y 1/ 3 ] Luku l_a on viiden luvun tulo, luvuista l_b1,..., l_b5 kukin on kolmen kuutiojuuren tulo niin, että jokainen kuutiojuuri esiintyy täsmälleen kolme kertaa. (%i52) l_b1*l_b2*l_b3*l_b4*l_b5; (%o52) u v w x y (%i53) l_a - l_b1*l_b2*l_b3*l_b4*l_b5; (%o53) 0 Erotus on nolla, kkuten pitääkin. Testataan sama numeerisilla arvoilla: (%i54) [u,v,w,x,y]:[7919.0, 7927.0, 7933.0, 7937.0, 7949.0]$ (%i55) l_a:u*v*w*x*y$ (%i56) [l_b1:(u*v*w)^(1/3), l_b2:(v*w*x)^(1/3), l_b3:(w*x*y)^(1/3), l_b4:(u*x*y)^(1/3), l_b5: (u*v*y)^(1/3)]$ (%i57) l_a - l_b1*l_b2*l_b3*l_b4*l_b5; (%o57) 159744.0 Erotuksen pitäisi olla nolla! Ongelma piilee siinä, että syntyvät tulot ovat niin suuria, että erotukseen jää vain pyöristysvirheitä. (%i58) kill(u,v,w,x,y,l_a,l_b1,l_b2,l_b3,l_b4,l_b5); (%o58) done 1.11 Riittääkö 16 numeron tarkkuus, B? (%i59) kill(values); (%o59) done Lasketaan kosinin arvo piin monikerrassa, kun kerroin on suuri kokonaisluku. (Tämä ogelma on peräisin erään pro gradun Fourier-sarjatarkasteluista.) (%i60) cos(%pi*a^n*x); (%o60) cos π a n x (%i61) (a:7, n:50)$
SL_esim_L1.wxm 7 / 8 Muuttujan a arvo on 0.1 aluksi normaalin tarkkuuden mukaisesti (16 numeron tarkkuus): (%i62) x1:0.1$ (%i63) float(cos(%pi*a^n*x1)); (%o63) -.4822323627440639 Lasketaan seuraavaksi sama käyttäen suurtarkkuuslaskentaa (bfloat(...), fpprec:50 laskee k.o. suureen 50 numeron tarkkuudella): (%i64) x1:1/10$ (%i65) bfloat(cos(%pi*a^n*x1)), fpprec:50; (%o65) - 9.5105651628371033860478657103850885757985117517066b-1 (%i66) float(%); (%o66) -.9510565162837104 Tulos eroaa aiemmin lasketusta merkittävästi; missä vika? (%i67) a^n*x1; (%o67) 1798465042647412146620280340569649349251249 10 (%i68) k1:floor(a^n*x1); (%o68) 179846504264741214662028034056964934925124 (%i69) s1:mod(a^n*x1, 1); (%o69) 9 10 (%i70) a^n*x1=k1+s1; (%o70) 1798465042647412146620280340569649349251249 = 1798465042647412146620280340569649349251249 10 10 (%i71) is(%); (%o71) true Laskettavana on siis cos(%pi*k + %pi*s), kun k=k1 ja s=s1: (%i72) trigexpand(cos(%pi*k+%pi*s)); (%o72) cos π k cos π s - sin π k sin π s (%i73) declare(k, integer); (%o73) done (%i74) cos_ks:trigexpand(cos(%pi*k + %pi*s)); (%o74) - 1 k cos π s (%i75) remove(k, integer); (%o75) done Kosinin jaksollisuuden takia laskettavana on luku: (%i76) ev(cos_ks, k=k1, s=s1); (%o76) cos 9 π 10
SL_esim_L1.wxm 8 / 8 (%i77) float(%); (%o77) -.9510565162951535 Ongelma näkyy seuraavastakin: kun lasketaan tarkalla piin arvolla, on piin monikerroissa (%i78) [cos(k1*%pi), sin(k1*%pi)]; (%o78) [ 1, 0 ] Mutta kun luvulle k1*%pi lasketaan ensin likiarvo (oletustarkkuus on vain 16 numeroa), saadaan (%i79) k1_pi:float(k1*%pi); (%o79) 5.650044565719163 10 41 (%i80) [cos(k1_pi), sin(k1_pi)]; (%o80) [ -.4822323627440639, -.8760433484264791 ] (%i81) kill(values)$