PLA-31100 OHJELMOINTITEKNIIKKA Syksy 2015 Mika Saari PLA-31100 Kurssin sisältö • Suoritusperusteet • Työvälineet ohjelmoinnin opiskeluun • Algoritminen Ajattelu • Javan kirjoitustyyli, Tietotyypit ja operaatiot • Ohjausrakenteet (if, switch, for, while, jne…) • Taulukko • Ensimmäinen välitentti • Merkkijonot • Metodit(Funktiot tai aliohjelmat) • Toinen välitentti 3 Kurssin suoritus • Kurssin kahdesta tentistä saa kummastakin enintään 10 pistettä ja harjoituksista enintään 10 pistettä eli kurssin maksimipistemäärä on 30. Arvosana määräytyy oheisen taulukon mukaan. • Tentit ovat ohjelmointitehtäviä. • Tenttiohjelman arviointikriteerit ovat: kääntyy(2), tekee annetun tehtävän(3), ratkaisulogiikka(3), luettavuus(2). • Harjoitus- ja tenttipisteet huomioidaan kevään 2016 uusintatenteissä. • Uusintatenttejä on kaksi ja ne kattavat kurssin koko aihealueen. PISTEET 27 ARVOSANA 24 21 18 15 5 4 3 2 1 <15 0 • Yhdellä uusintatentillä voi korvata yhden tenttisuorituksen. • Luentomateriaali, luennolla laaditut ohjelmat, harjoitustehtävät ja harjoitusten mallivastaukset löytyvät verkko-osoitteesta http://www.students.tut.fi/~saari5/PLA_31100_2015/ 4 Kurssin suoritus - harjoitukset • Harjoituksen jokaisesta kolmesta tehdystä tehtävästä saa 1 pisteen (hyvä yritys riittää). • Opiskelija lähettää harjoitusohjelmansa sähköpostin liitteenä osoitteeseen mika.saari@tut.fi eräpäivään mennessä. • Harjoitus- ja tenttipisteet huomioidaan kevään 2016 uusintatenteissä. • Harjoituksia ei voi korvata eräpäivän jälkeen. • Harjoitustehtävien esimerkkiratkaisut käydään läpi harjoitustunneilla (eräpäivän jälkeen) • Luentomateriaali, luennolla laaditut ohjelmat, harjoitustehtävät ja harjoitusten mallivastaukset löytyvät verkko-osoitteesta http://www.students.tut.fi/~saari5/PLA_31100_2015/ • Luennoilla ja harjoituksissa ei ole läsnäolopakkoa. • Palautetta omiin harjoitustehtäväratkaisuihin saa harjoitustuntien aikana. 5 Java-kirjoja • Mika Vesterholm, Jorma Kyppö: Java-ohjelmointi, Talentum 2008, ISBN 978-952-14-1356-8 • Simo Silander, Vesa Ollikanen, Juha Peltomäki: Java, WSOY 2010, ISBN 978-951-846-237-2 • Jukka Harju, Jukka Juslin: Java-ohjelmointi – opas ammattimaiseen osaamiseen, Readme.fi 2009, ISBN 978-952-220-084-6 http://courses.caveofprogramming.com/course/java-for-complete-beginners/ 6 Java-ohjelmointikielen yleisyys TIOBE Programming Community Index (ohjelmoijia, kursseja, toimijoita) 7 Java-ohjelmointikielen yleisyys TIOBE Programming Community Index (ohjelmoijia, kursseja, toimijoita) 2014 2013 1 2 2 kieli % %muutos C 16 +0.43 1 Java 15 -0.99 3 4 Objective-C 10 +1.47 4 3 C++ 5 -4.68 5 7 Basic 4 -0.24 6 6 C# 3 -2.71 7 8 Python 3 -0.48 8 5 PHP 2 -3.83 9 11 Perl 2 +0.18 10 9 JavaScript 2 +0.08 11 - Visual Basic 1 +2.01 12 13 Visual Basic.NET 1 -0.01 13 10 Ruby 1 -0.83 14 23 F# 1 +0.56 15 18 Pascal 1 +0.42 16 12 Transact-SQL 1 -0.35 17 38 ActionScript 1 +0.69 18 14 Delphi 1 -0.00 19 16 Lisp 1 +0.08 20 17 PL/SQL 1 +0.03 8 Ohjelmointikielten käytön kehitys 9 OHJELMANKEHITYS JAVA-YMPÄRISTÖSSÄ 10 Ohjelman suoritus tietokoneessa KESKUSYKSIKKÖ käskykanta levymuisti keskusmuisti prosessori compile execute Editori Ohjelma Kääntäjä/Tulkki open save tiedostot Ohjelma Tiedot 11 Java-kielen tulkitseminen ”AJAMINEN” SYÖTTÖTIEDOT ohjelma.java OMA OHJELMA LAUSEKIELELLÄ Editori JAVAC KÄÄNTÄJÄ KONEKIELELLÄ ohjelma.class OMA OHJELMA VÄLIKIELELLÄ (tavukoodi) JAVA TULKKI JVM:ssä (JRE) JDK JAVAN KIRJASTOT TULOSTIEDOT 14 Työvälineiden asennus • Java SE 8 (JDK, JRE) – dokumentaatio • Eclipse Mars • NetBeans 8.0 • Linkit kurssin sivuilla • Käyttöopetus harjoituksissa 15 Editori ja dokumentaatio 16 Projekti, lähdekielihakemistot , package, luokka,… ALGORITMINEN AJATTELU 17 Ongelman hahmottaminen ohjelmaksi PALVELU Input → Output 4 8 KESKIARVO 6 TIEDOT Muuttujat TOIMINTA Prosessi LUKU1 LUVUT Puoliohjelma Peräkkäin Toisto Valinta VASTAUS LUKU2 Tiedot toiminnan kuvauksesta 1. Lisää summaan annetut luvut 2. Jaa summa lukujen määrällä VASTAUS Hahmottamisprosessi ongelmasta ratkaisuun: toiminnan ymmärtäminen + algoritmin keksiminen + tekniikan osaaminen + ohjelmointitekniikkaa 18 Keskiarvo-vuokaavio KESKIARVO LUE LUKU LUKU >= 0 K E VASTAUS= VASTAUS / N VASTAUS= VASTAUS+LUKU N=N+1 TULOSTA VASTAUS LOPPU 19 Keskiarvo-puoliohjelma PERÄKKÄISYYS VASTAUS = 0, N = 0, LUKU LUVUT L: LUE LUKU JOS LUKU < 0 MENE LOPPU VALINTA Peräkkäin Valinta Toisto VASTAUS VASTAUS = VASTAUS + LUKU N=N+1 MENE L LOPPU: VASTAUS=VASTAUS / N TOISTO TULOSTA VASTAUS 20 Java-ohjelman rakenne PUOLIOHJELMA VASTAUS = 0, N = 0, LUKU L: JAVA-OHJELMA public class Keskiarvo { public static void main(String[] args) { LUE LUKU double vastaus=0, luku; int n=0; JOS LUKU < 0 MENE LOPPU luku = Lue.desi( ); while (luku != 0) { vastaus = vastaus + luku; vastaus += luku; n = n + 1; n++; luku = Lue.desi( ); } vastaus = vastaus / n; vastaus /= n; System.out.println(”Keskiarvo on ”+vastaus); VASTAUS = VASTAUS + LUKU N=N+1 MENE L LOPPU: VASTAUS=VASTAUS / N TULOSTA VASTAUS } } 21 Ohjelman laatimisen vaiheet ● ● Editori kuntoon ● Perspektiivit, working setit, workspacet, … Projektit ● Lähdekoodikansiot (java) ● Package-kansiot Tuloskoodikansio (class) Koodin kirjoitus editorilla Kääntäminen Virheen jäljitys ● Välitulosteet ● Debuggaus Testaus Integrointi järjestelmään Käyttöönotto ● ● ● ● ● ● ● 22 Luentoharjoitus 1 Minkälaisia asioita teet päivittäin a) peräkkäin b) toistuvasti c) valitsemalla Eroaako ihminen tietokoneesta ? 23 Luentoharjoitus 2 Tehdään ohjelma, joka antaa käyttäjän pelata sudokua. Minkälaisia tehtäviä ja missä järjestyksessä ne suoritetaan. 24 Luentoharjoitus 3 Muuttuja SALDO = 10 000 euroa. Muuttuja KORKO = 4 %. Muuttuja VUODET = 5 vuotta. Laadi (puoli)ohjelma, joka kertoo, kuinka paljon rahaa tilillä on VUODET-muuttujan osoittaman vuosimäärän kuluttua. KorkoWhile.java 25 Luentoharjoitus 4 Laadi radioaktiivisen aineen puoliintumisen laskeva (puoli)ohjelma siten, että ohjelma ilmoittaa, milloin radioaktiivisuuden taso on laskenut alle annetun arvon. Mitä muuttujia ohjelmassa tarvitaan? Puoliintumisaika.java 26 JAVAN KIRJOITUSTYYLI TIETOTYYPIT OPERAATIOT http://www.oracle.com/technetwork/java/javase/documentation/codeconvtoc-136057.html 28 Sijoittelu Tekstin jako riveille Sisennykset Välilyönnit while (paaoma > 0) { velkaMarkat = paaoma - lyhennys; if (velkaMarkat <= 0) System.out.println(”Laina maksettu”); else { paaoma = velkaMarkat; System.out.println(”Lainaa jäljellä”); } } 29 Kommentit /* Usearivisiä kommentteja voi rajata näin */ // Loppurivi tulkitaan kommentiksi lyhennys=paaoma; // Tässä kommentoin yhtä riviä /** Javadoc-ohjelma näyttää tämän dokumentoinnissa */ 30 Kommentit /******************************************************************************* Kuvaus: Ohjelma laskee annetun luvun kertoman (tehtävä 22) Tekijä: Mika Saari pvm: 10.8.2012 (opiskelijanumero) Muutettu: 9.8.2015 ms Syöttötietojen tarkistus lisätty Julkiset metodit: public void lueLuku() kysyy luvun public int tulostaLuku() tulostaa kertoman *****************************************************************************/ 31 Tunnukset • Tunnukseksi kutsutaan nimeä, jonka ohjelmoija antaa jollekin nimettävälle asialle: muuttujalle, metodille, vakiolle, luokalle,… • Tunnusten nimet ovat pituudeltaan rajoittamattomia – – – – • • • • • merkkejä, numeroita Unicode: å, ä, ö pienet ja isot kirjaimet ovat eri merkkejä (palkka, Palkka) luokkien nimissä ei å, ä, ö merkkejä Muuttujien nimet on hyvä alkaa pienellä kirjaimella Monisanaiset muuttujien toinen, kolmas jne. sanat alkavat isoilla kirjaimilla Silmukkalaskureina käytetään lyhyitä (yksikirjaimisia) muuttujanimiä Luokkien nimet alkavat isolla kirjaimella Vakiot kirjoitetaan kokonaan isolla 32 Lyhenteitä Eclipseen • • • • • • • • • main-rivi: main ctrl+space+enter tulostus: syso ctrl+space Esisyöttö: ctrl+space delete line: ctrl+d duplicate line: alt+d format: ctrl+shift+f rename: alt+shift+r rivin siirto: alt+up/down importit: ctrl+shift+o 33 Tunnukset int laskuri, kuukaudenNumero, palkkaVero; for (int i=0; i<100; i++)… Luokan nimi public class Auto { Vakiot final int KKLKM = 12; 34 Biteistä tietotyypeiksi OHJELMA luku=arvo+2 TIEDOT ASIAKAS string etunimi string sukunimi int luku string osoite ADD R1,123 Kalle Kehveli 45 Kotikuja 5 KalleKehveli45Kotikuja 5 tulkinta/koodaus? 1001100100100111 1001100100100111 35 Muuttujan rakenne ● • • Yksi kenttä: muuttuja = arvo Rakenne eli monta kenttää: muuttuja = osoite Esimerkiksi: Asetus Vertailu • – summa = palkka; henkilö = asiakas; summa == palkka; henkilö == asiakas; KESKUSMUISTI OHJELMA 9500 palkka Asiakas • • • nimi kunta saldo kuukaudet[ ] KALLE VIRTANEN PORI 10000 31 28 31 30 31 30 31 31 30 31 30 31 36 Perustietotyypit TYYPPI BITTEJÄ ARVOALUE byte 8 -128 – 127 short 16 -32768 - 32767 int 32 -2147483648 - 2147483647 long 64 -9223372036854775808 – 9223372036854775807 float 32 1.4*10-45 – 3.4*1038 (7 tarkkuus) double 64 4.9*10-324 – 1.8*10308 (15 tarkkuus) char 16 ’a’ ’\n’ ’\\’ numero (Unicode koodi) boolean true, false enum {arvoluettelo} 37 Tyyppimuunnokset AUTOMAATTINEN MUUNNOS int a; long b; b = a; byte short char int float long double 8 16 16 32 32 64 64 OHJELMOIJAN TEKEMÄ TYYPPIMUUNNOS int a; long b; a = (int) b; Järkevissä tapauksissa tehdään järkeviä katkaisuja. Järjettömissä tapauksissa vastuu on ohjelmoijalla. 38 Luentoharjoitus 5 Mitkä tietotyypit ovat sopivia seuraaville tiedoille? • Nimi • Palkka • Ikä • Syntymäaika • Puhelinnumero • Tieto luottokelpoisuudesta Google: ”java api String” 39 Perusoperaatiot (presedenssi ja assosiatiivisuus) [ ] . ( ) e++ e-++e --e +e -e ! ~ new (tyyppi)e * / % + << >> >>> < > >= <= == != eka = toka = 6; >> säilyttää etumerkin << ja >>> lisää nollan & ^ | && || ?: = += -= *= /= %= <<= >>= >>>= &= ^= |= 40 Esimerkki (operaatioita) /*Keskiarvon laskentaohjelma Markku Nevanranta 31.8.2009 */ public class Keskiarvo { public static void main(String[] args) { double vastaus=0, n=0, luku; luku = Lue.desi( ); while (luku != 0) { vastaus += luku; //kerätään summaa n++; //lasketaan lukujen määrä luku = Lue.desi( ); } vastaus /= n; System.out.println(”Keskiarvo on ”+vastaus); } } 41 Esimerkki (assosiatiivisuus) a b c a = 1; b = 5; c = 10; 1 5 10 a--; 0 5 10 a = a++ +b; 5 5 10 c += a*--c; 5 5 55 a = 2*c /(-a); -22 5 55 b = c % (b-1); -22 3 55 -- vähentää muuttujan arvoa yhdellä ++ lisää muuttujan arvoa yhdellä % jakojäännös 42 Esimerkki (bittioperaatiot) public class Maski { public static void main(String[] args) { final int LUKU = 1; //001 final int KIRJOITUS = 2; //010 final int SUORITUS = 4;//100 int liput = 0; liput |= LUKU; //liput = 001 liput |= KIRJOITUS; //liput = 011 if ((liput & KIRJOITUS) == KIRJOITUS) System.out.println(”On oikeus kirjoittaa”); } } 43 Lukeminen (Scanner) 1. Scanner-luokkaa käyttäen • Käsittelee tietovirrasta tulevaa merkkijonoa import java.util.Scanner; Scanner lukija = new Scanner(System.in); System.out.println(”Anna luku: ”); luku = lukija.nextInt(); KorkoScanner.java 45 Lukeminen (Lue.java) Lukeminen voidaan tehdä monella tasolla: 2. Lue-luokkaa käyttäen • Rakennetaan itse omaan tarpeeseen sopiva luokka luku = Lue.koko(”Anna luku: ”); Lue.koko() lukee kokonaisluvun Lue.desi() lukee desimaaliluvun Lue.rivi() lukee rivin tekstiä Lue.merkki() lukee yhden merkin Lue.totuus() lukee totuusarvon KorkoWhile.java 46 Lukeminen (tietovirta) 3. Tietovirtoja käyttäen static BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); public static int kluku(){ int arvo=-1; boolean ok; do { try { arvo=Integer.parseInt(stdin.readLine()); ok=true; } catch (Exception e) { System.out.println("Kelvoton kokonaisluku. Anna uusi!"); ok=false; } } while (!ok); return arvo; } 47 Tulostus System-luokan out-tietovirtaluokan metodeita* Muotoilematon • System.out.println (”tulostuva teksti ja rivinvaihto”); • System.out.print (”teksti ilman rivinvaihtoa”); • System.out.println (”hinta on ”+maksu+” euroa”); • System.out.println (”hinta on ”+(maksu+1.5*vero)+” euroa”); Muotoiltu • System.out.printf(”vakioteksti ja mutoilut”,muuttujaluettelo); • System.out.printf(”hinta on %d euroa\n”, maksu); • System.out.printf(”hinta on %5d euroa\n”, maksu); System.out.printf(”hinta on %.2f euroa\n”, maksu*vero); • System.out.printf(”hinta on %10.2f euroa\n”, maksu*vero); //pyöristys • System.out.printf(”Tässä teksti\n %s\nteksti loppui”, teksti); * katso dokumentaatiota (Formatter-luokka tai System.out.printf (format string syntax)) 48 Luentoharjoitus public class Presedenssi { public static void main(String[ ] args) { int luku=5, tulos1, tulos2, tulos3, tulos4; tulos1 = luku++ + luku++; tulos2 = ++luku + ++luku; tulos3 = luku++ + ++luku; tulos4 = ++luku + luku++; tulos1= 11 tulos2= 17 tulos3= 20 tulos4= 24 System.out.println(tulos1+” ”+tulos2+ ” ”+tulos3+” ”+tulos4); } } 49 OHJAUSRAKENTEET 50 IF-ehtolause if (ehto) lauseet else lauseet LOHKO ELI KOOTTU LAUSE if (ika>20) tulot=opintolaina; else tulot=100; if (ika>20) { tulot=opintolaina; vuokra=1000; } else { tulot=100; karkkiin=30; } 51 Ehto-osa VERTAILUOPERAATIOT > >= < <= == != Loogiset metodit LOOGISET OPERAATIOT && || ^ ! ja tai xor ei 52 Monitasoinen IF if (koulutus.equals(”DI”)) { if (ohjelmointitaito==’k’) palkka=20000; } else palkka=15000; if (koulutus.equals(”DI”)) { if (ohjelmointitaito==’k’) palkka=20000; } else palkka=15000; if (koulutus.equals(”DI”)) if (ohjelmointitaito==’k’) palkka=20000; else palkka=15000; palkka=15000; if (koulutus.equals(”DI”) && ohjelmointitaito==’k’) palkka=20000; Huomaa! Ulompi if sisältää yhden lauseen – ei sulkeita Vastaako valkoista tai vihreää ehtoa? 53 IF-esimerkkejä Onko samat? if (ika<=20 && omaisuus>=1000000)… if (ika>20 || omaisuus<1000000)… Kumpi ehto-lauseke valitsee nuoren miljonäärin? Onko jälkimmäinen sama kuin edellinen jos edessä ! Kuka saa seuraavissa tapauksissa halvan pääsylipun? if (ika<15 || ika>65 && opiskelija==’k’)… if ((ika<15 || ika>65) && opiskelija==’k’)… Miten korjaisit lauseen siten, että nuori, vanha tai opiskelija saa halvan pääsylipun? 54 Esimerkki (ehto-operaattori) if (arvosana>0) System.out.println(“Tentti on hyväksytty”); else System.out.println(“Tentti on hylätty”); System.out.println(“Tentti on “ + (arvosana>0 ? “hyväksytty” : “hylätty”)); 55 SWITCH-valintalause switch (lauseke) { case vakio1: lauseet; break; case vakio2: case vakio3: lauseet; case vakio4: lauseet; break; default: lauseet; break; } 56 SWITCH-esimerkki1 int kk; do { kk=Lue.koko(); switch (kk) { case 1: System.out.println(”Tammikuu”); break; case 2: System.out.println(”Helmikuu”); break; case 3: System.out.println(”Maaliskuu”); break; case 4: System.out.println(”Huhtikuu”); break; case 5: System.out.println(”Toukokuu”); break; case 6: case 7: case 8: System.out.println(”Kesä”); break; case 9: System.out.println(”Syyskuu”); break; case 10: System.out.println(”Lokakuu”); break; case 11: System.out.println(”Marraskuu”); break; case 12: System.out.println(”Joulukuu”); break default: System.out.println(”Virheellinen kuukausinumero”); } } while (kk != 0); 57 SWITCH-esimerkki2 String kk; do { kk=Lue.rivi(); switch (kk) { case "Maaliskuu": case "Huhtikuu": case "Toukokuu": System.out.println("Kevät"); break; case "Kesäkuu": case "Heinäkuu": case "Elokuu": System.out.println("Kesä"); break; case "Syyskuu": case "Lokakuu": case "Marraskuu": System.out.println("Syksy"); break; case "Joulukuu": case "Tammikuu": case "Helmikuu": System.out.println("Talvi"); break; default: System.out.println("Virheellinen kuukausi"); } } while (kk.equals("")); 58 WHILE-toistolause while (jatkamisehto) toistettavat lauseet jatkamisehto suoritetaan joka toistokerran alussa ja toistettavat lauseet suoritetaan jos jatkamisehto on tosi 59 WHILE-esimerkkejä int i=0; while (i<5) { System.out.println(i); i++; } int i=0; while ( i<5) System.out.println(i++); int luku=Lue.koko(); while (luku != 0) { System.out.println(luku); luku=Lue.koko(); } int luku; while ((luku=Lue.koko()) != 0) System.out.println(luku); 60 FOR-toistolause for (alkuasetus; jatkamisehto; etenemisaskel) toistettavat lauseet alkuasetus suoritetaan kerran ennen toistojen aloittamista jatkamisehto totuusarvoinen lauseke, joka tarkistetaan ennen jokaista toistokertaa ja jos se on tosi suoritetaan toistettavat lauseet etenemisaskel lause joka suoritetaan jokaisen toistokerran jälkeen 61 FOR-esimerkkejä for (int i=0; i<6; i++) System.out.println(i*i); for (int i=0, j=10, k=1; i<6 && j>2; i++, j--) { System.out.println(i*j*k); k++; } Onko jatkamisehto järkevä? 62 FOREACH-tyyppinen toistolause for (tyyppi muuttuja: kokoelma) toistettavat lauseet tyyppi kokoelmasta poimittavan tiedon tyyppi muuttuja kokoelmasta poimittava tieto kokoelma kokoelma josta tietoalkiot poimitaan yksi kerrallaan ja sillä suoritetaan toistettavat lauseet 63 FOREACH-esimerkki taulu for (int luku : taulu) System.out.println(luku); 2 45 56 64 67 DO-toistolause do toistettavat lauseet while (jatkamisehto) Miten eroaa while-lauseesta? 65 DO-esimerkki do { System.out.println(”Anna luku: ”); luku = Lue.koko(); System.out.println(luku); } while (luku != 0); Mitä hyötyä vastaavaan while-lauseeseen? 66 BREAK-lause Break keskeyttää switch- tai toistolauseen suorituksen for (int i=1; i<100; i++) { if (i%5 == 0) break; System.out.println(i); } 67 BREAK-lause Pelkkä break keskeyttää vain sisemmän rakenteen suorituksen for (int i=0; i<3; i++) for (int j=0; j<3; j++) { if (i == j) break; System.out.println(taulu[i][j]); } Osoitteellinen break keskeyttää rakenteen, johon osoite viittaa ulompi: for (int i=1; i<9; i++) // sudokuruudukon täyttö for (int j=1; j<9; j++) if (vapaa(i,j)){ asetaPuuttuvaNumero(i,j); break ulompi; } 68 CONTINUE-lause Keskeytetään toiston meneillään oleva kierros ja aletaan seuraava kierros for (int i=1; i<1000; i++) { if (i%7 == 0) continue; System.out.println(i); } keskeytetään ulomman silmukan meneillään oleva kierros ja aletaan seuraava kierros ulompi: for (int i = 0; i < 10; i+=2) { for (int j = 0; j < 20; j++) if (taulu[i][j] == 0) continue ulompi; System.out.println("Löytyi riviltä " + i); } 69 Luentoharjoitus 6 Tulosta kaikista syöttämistäsi luvuista suurin ja pienin. 70 Luentoharjoitus 7 Muunna korko-ohjelma for-silmukkaa käyttäväksi. Jäljitä ohjelman kulku ”debuggerilla”. 71 Luentoharjoitus 8 Tee ohjelma, joka antaa halutun määrän alkulukuja* yhdestä lähtien. * Alkuluku on 1 suurempi luonnollinen luku (positiivinen kokonaisluku), joka on jaollinen vain 1:llä ja itsellään. 72 Luentoharjoitus 9 Vuosi on karkausvuosi, jos se on jaollinen 4:llä, mutta ei sadalla. 400:lla jaolliset kuitenkin ovat karkausvuosia. Laadi vuorovaikutteinen sovellus, joka tulostaa karkausvuodet käyttäjän pyytämältä vuosilukuväliltä. 73 Luentoharjoitus 10 Tutki, paljonko sinulla on rahaa 30 vuoden päästä, jos sijoitat nyt 1000 euroa kasvuosakkeeseen ja vuosittainen tuotto on 8 prosenttia ja pankin vuosittainen hallinnointikustannus on a) 0 prosenttia b) 2 prosenttia. Kasvuosake = vuosittain tuotto lisätään pääomaan 74 TAULUKKO 76 Taulukko on olio int[ ] jono = new int[5]; jono 0 0 0 0 0 0 1 2 3 4 77 Moniulotteiset taulukot int[ ] jono = new int[5]; 0 1 2 0 0 0 0 double[ ][ ] taulu = new double[3][5]; char[ ][ ][ ] merkit = new char[3][5][4]; 1 3 4 0 2 0 3 4 0 0.0 0.0 0.0 0.0 0.0 1 0.0 0.0 0.0 0.0 0.0 2 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 78 Taulukon alustus int[ ] jono = new int[5]; jono[3] = 8; int[ ] jono = {1,8,3,4,2}; jono 0 0 0 0 8 0 1 2 3 4 4 2 jono 1 0 8 1 3 2 3 4 79 Taulukon alustus String[ ] nimet = {”Liisa”,”Aki”,”Ville”,”Juha-Matti”,”Mia”}; Liisa 1 Aki 2 Ville 3 Juha–Matti 0 4 Mia boolean[ ][ ] totuus = {{true,true,false}, {false,true,false}}; true true false false true false 80 Taulukkosääntöjä Taulukon alkiot ovat samaa tyyppiä Indeksi int-tyyppinen Ensimmäisen alkion indeksi on 0 Vasta suoritusvaiheessa huomataan indeksin ylitys Rivien määrä: taulu.length Sarakkeiden määrä: taulu[3].length Taulukot alustetaan aina (olio) Taulukkomuuttuja voi osoittaa eri taulukko-olioihin kunhan ne ovat samanmuotoisia ja -tyyppisiä • Taulukot eivät automaattisesti kasva suorituksen aikana, mutta ohjelmoija voi pidentää taulukkoa • • • • • • • • 81 Taulukon läpikäynti for (int i=0; i<6; i++){ for (int j=0; j<4; j++) System.out.print(taulu[i][j]); System.out.println(); } for (int i : taulu[2]) System.out.println(i); for (int[] i: taulu) for (int j: i) System.out.println(j); taulu 2 45 56 67 89 2 88 7 67 56 12 45 9 2 2 5 1 2 5 33 22 5 55 44 82 Epätasainen taulukko Tasainen taulukko 1 2 int[ ][ ] taulu = new int[3][2]; 5 9 int[ ][ ] taulu = {{1,2}, {5,9}, {3,2}}; 3 2 taulu Epätasainen taulukko int[ ][ ] taulu = new int[3][ ]; taulu[0] = new int[2]; taulu[1] = new int[3]; taulu[2] = new int[1]; 83 Epätasaisen taulukon alustus Toimiiko molemmat? int[ ][ ] matriisi = {{1,2}, {5,9,7}, {3}}; taulu int[ ][ ] taulu = new int[3][ ]; taulu[0] = {1,2}; taulu[1] = {5,9,7}; taulu[2] = {3}; 1 2 5 9 7 3 84 Esimerkkejä public class Taulu { public static void main(String[] args) { int[ ] jono= {3,0,7,2,9}; int[ ][ ] taulu= {{2,4,6},{20,40,60}}; for(int i=0; i<jono.length; i++) System.out.print(jono[i]+" "); System.out.println(); for(int i=0; i<taulu.length; i++){ for(int j=0; j<taulu[i].length; j++) System.out.print(taulu[i][j] + " "); System.out.println(); } } } 85 Esimerkkejä int[ ] jono = new int[5]; 0 0 0 0 0 int[ ] sarja = {2,4,6,8,3}; 2 4 6 8 3 sarja = jono; Mitä tapahtuu alemmalle taulukolle? Voit muuttaa tietoa toisen viitteen kautta ja muutos näkyy toisenkin viitteen kautta. 86 Javan taulukkoluokkia • System.arrayCopy • ArrayList • Arrays – – – – – – asList binarySearch equals fill Sort toString 87 Luentoharjoitus 11 Koskien yksiulotteista positiivisten kokonaislukujen taulukkoa tulosta a) b) c) d) e) alustettu taulukko taulukon arvojen summa ensimmäisen nollan indeksi taulukon suurin arvo ja sen indeksi taulukon arvojen prosentuaaliset osuudet (8.1) 88 Luentoharjoitus 12 Tee ohjelma, joka automaattisesti laajentaa taulukkoa, kun lisäät siihen liikaa lukuja. 89 Luentoharjoitus 13 Tee ohjelma, joka tarkastaa antamasi lottorivin satunnaisesti luodun lottorivin kanssa. (8.6) * Math.random() antaa satunnaisluvun väliltä [0,1[ 90 Luentoharjoitus 14 Tutki, montako satunnaislukua* suunnilleen pitää tuottaa välillä 1-10, jotta kaikkia lukuja alkaa tulla suunnilleen sama määrä. (8.12) * Math.random() antaa satunnaisluvun väliltä [0,1[ 91 Luentoharjoitus 15* Yksiulotteinen taulukko kuvaa joukko-opin joukkoa, jossa sama luku ei esiinny kahdesti. Laadi kahden joukon välille vähintään seuraavat kolme joukko-opin operaatiota, joista kukin palauttaa tulosjoukon1. YHDISTE yhdistää joukot tulosjoukoksi. LEIKKAUS palauttaa tulosjoukon, jossa on vain yhteiset alkiot. EROTUS palauttaa tulosjoukossa vain ne ensimmäisen joukon alkiot, joita ei ole toisessa joukossa. 1) Voi käyttää tyypillisiä taulukon toimintoja: poista duplikaatit, tiivistä, lajittele,... 92 Luentoharjoitus 16 Kaksiulotteisen taulukon harjoittelua: ● Taulukon luonti ● Tulostus ● Arvojen arvonta ● Keskiarvo ● Pienin ja indeksit rivi ja sarake ● Rivien suurimmat ● Muutetaan sarakkeen arvoja 93 MERKKIJONO 97 Merkkijono-olion luonti Merkkijono String lemmikki = ”kissa”; Merkkitaulukko char[ ] eläin = {’k’, ’o’, ’i’, ’r’, ’a’}; Merkkijonotaulukko String[ ] tarha = {”leijona”, ”seepra”, ”kameli”}; 98 Merkkijono metodit public int length() String jono = ”kissa”; int pituus = jono.length(); antaa merkkijonon pituuden // pituus=5 public boolean equals(String) palauttaa true jos merkkijonot samat do { System.out.println(”Jatkatko (kyllä tai ei) ”); String vastaus = Lue.rivi(); } while (vastaus.equals(”kyllä”)); public boolean equalsIgnoreCase(String) 99 Merkkijono metodit public int compareTo(String) Palauttaa numeron, joka ilmaisee merkkijonojen aakkosjärjestyksen: <0 verrattava merkkijono on ennen parametrimerkkijonoa == 0 merkkijonot ovat samat >0 verrattava merkkijono on parametrimerkkijonon jälkeen System.out.print(”Anna eka merkkijono ”); String eka = Lue.rivi(); System.out.print(”Anna toka merkkijono ”); String toka = Lue.rivi(); int jarjestys= eka.compareTo(toka); if (jarjestys < 0) System.out.println(”Eka ensin”); if (jarjestys == 0) System.out.println(”Yhtäsuuret”) if (jarjestys > 0) System.out.println(”Toka ensin”): 100 Merkkijono metodit public String toLowerCase() Muuttaa merkkijonon pieniksi kirjaimiksi. public String toUpperCase() Muuttaa merkkijonon isoiksi kirjaimiksi. String lemmikki = ”Kissa”; lemmikki = lemmikki.toLowerCase(); System.out.println(lemmikki+lemmikki.toUpperCase()); public String trim() Poistaa merkkijonon alusta ja lopusta välilyönnit. String lemmikki = ” Kissa”; lemmikki = lemmikki+”eläin ”; System.out.println(lemmikki.trim()); 101 Merkkijono metodit public char charAt(int index) Palauttaa merkkijonon yhden merkin. Huomaa kuvaava parametrin nimi. String lemmikki = ”Kissa”; for (int i=0; i<lemmikki.length(); i++) System.out.println(lemmikki.charAt(i)); Mitä tekee alla olevat metodit? public int indexOf(int char) public int indexOf(int char, int fromIndex) public int indexOf(String) public int indexOf(String, int fromIndex) Huomaa metodin kuormittaminen. 102 Merkkijono metodit public String substring(int startInd, int endInd) Palauttaa merkkijonosta osamerkkijonon lähtien merkkipaikasta startInd merkkiin endInd-1 asti. String lemmikki=”lemmikkikissa”; String suosikki=lemmikki.substring(3,8); //mikki String teksti = ”Hyvä ? olet voittanut paljon rahaa!”; String nimi = Lue.rivi(); String kirje = teksti.substring(0,5)+nimi+teksti.substring(6); Hyvä Mika Saari olet voittanut paljon rahaa! 103 String on muuttamaton // String-merkkijonoa ei voi muuttaa // mutta String-muuttujan voi kytkeä uuteen merkkijonoon // Markku Nevanranta public class Merkkijono { public static void main(String[] args) { String teksti = "Markku"; String nimi = "Harri"; teksti = "Liisa"; System.out.println(teksti); teksti = teksti+nimi; System.out.println(teksti); nimi = teksti; System.out.println(nimi); nimi = ""+123; System.out.println(nimi); } } 104 Merkit merkkijonoksi Muunna merkkijonon A-merkit a-merkeiksi. public class MerkkiMuunnos{ public static void main(String[] args){ String teksti, tulos; teksti = Lue.rivi ("Anna merkkijono "); // Merkkijono merkkitaulukoksi char[] mtaulu = teksti.toCharArray(); for (int i=0; i<mtaulu.length; i++) if (mtaulu[i] == 'A') mtaulu[i] = 'a'; tulos = new String(mtaulu); System.out.println(tulos); // Toinen tapa tulos = teksti.replace('A','a');//parametrit voivat olla myös merkkijonoja System.out.println(tulos); } } 105 Merkkijonoista • • • • • Unicode-merkistö \uxxxx Escape-esitys (esim. \n, \t, \\, \”) Merkkijonon pituus tallessa merkkijono-oliossa Merkkien vertailu: vastaus == ’k’ Merkkijonojen vertailu: – lemmikki==”kissa” (väärin) – lemmikki.equals(”kissa”) (oikein) • Perustietotyyppi merkkijonoksi: – ”numero ”+luku+” tekstiksi” – String.valueOf(luku) • Merkkijono perustietotyypiksi: – Integer.parseInt(mjono) – new Integer(mjono) // JDK 1.2 // JDK 1.5 (Byte, Short, Integer, Long, Float, Double, Boolean, Char kääreluokissa vastaavat xValue()- ja parsex-metodit) 106 Merkkijonomuunnos esimerkki String luku = "123"; // Jos ei muistuta kokonaislukua syntyy keskeytys int a, b, c; // Numero tekstiksi String teksti = String.valueOf(12.34); System.out.println(teksti); // JDK 1.1 int a = Integer.valueOf(luku).intValue(); System.out.println(a); // JDK 1.2 int b = Integer.parseInt(luku); System.out.println(b); // JDK 1.5 int c = new Integer(luku); System.out.println(c); System.out.println(a+b+c); 107 StringBuilder • Käytä StringBuilder-merkkijonoa jos Stringmerkkijonoa muutetaan paljon • StringBufferin synkronoimaton versio • Metodeja: – – – – – – – length(), setLength(int) append(perustietotyyppi), insert(int paikka, perustietotyyppi) replace(int, int, String), delete(int, int) charAt(int), setCharAt(int, char) substring(int, int) toString() reverse() 108 StringBuilder esimerkki String kjono = "kenkä"; StringBuilder sb = new StringBuilder(kjono); sb.insert(0,"Puu"); //Puukenkä sb.append("kö"); //Puukenkäkö sb.delete(4,6); //Puukkäkö sb.replace(5,8,"o"); //Puukko String jono3 = sb.toString(); //jono3 = "Puukko" StringBuilder buf = new StringBuilder(); String jono = buf.append("Puu").append(kjono).toString(); 109 StringTokenizer • Pätkii merkkijonon osajonoiksi (token). • Metodeja: – – – – – – StringTokenizer(String) StringTokenizer(String, String delimiters) countTokens() hasMoreTokens() nextToken(), nextToken(String delimiters) String.split() metodilla saadaan myös pätkittyä 110 StringTokenizer esimerkki String pätkittävä = "Matti,Kalle,,Maija"; StringTokenizer st = new StringTokenizer(pätkittävä, ",", false); while ( st.hasMoreTokens() ) System.out.println(st.nextToken()); st = new StringTokenizer(pätkittävä, ",", true); while ( st.hasMoreTokens() ) System.out.println(st.nextToken()); Matti Kalle Maija Matti , Kalle , , Maija 111 Säännölliset lausekkeet • Säännöllisten lausekkeiden (regular expression, regexp) avulla määritetään merkkijonohahmoja, joita voidaan tunnistaa merkkijonosta • String-luokassa on säännöllisiä lausekkeita käyttäviä metodeita – Hahmoa etsitään matches-metodilla, joka palauttaa true-arvon jos hahmo löytyy muuten false – Merkkijono voidaan pilkkoa split-metodilla hahmoon täsmäävissä kohdissa ja pilkotut merkkijonopalaset palautetaan merkkijonotaulukkona – replaceAll-metodi korvaa kaikki hahmoon täsmäävät osat annetulla merkkijonolla – replaceFirst-metodi korvaa vain ensimmäisen hahmoon täsmäävän merkkijonon annetulla merkkijonolla • Pattern ja Matcher luokissa lisää metodeja 112 Hahmon muodostaminen • • • • • • • • Yksinkertainen hahmo: mikä tahansa hakasulkeissa oleva merkki kelpaa “rahayksikkö [€$£]”, “[ahjmprsv]aha” Arvoväli: mikä tahansa arvovälillä oleva merkki kelpaa “[A-E] ajokortti”, “arvot [1-3 7-9]” Yhdiste, leikkaus ja erotus: ehto sisällytetään toiseen ehtoon “[a-c[1-3]] luokat”, “[1-5&&[3-9]] luokat”, “[1-5&&[^3-9]] luokat” Merkkiluokat: mikä tahansa merkki (.), numerot 0-9 (\\d), muu merkki paitsi 0-9 (\\D), kaikki tyhjämerkit (\\s), ei-tyhjä merkki (\\S), mikä tahansa numero tai merkki (\\w), \\w negaatio (\\W) Ryhmittely ja takaisinviittaus: () merkitään yhdessä käsiteltävä ryhmä, \\numero kertoo montako kertaa ryhmää pitää toistua “(.)\\1” (merkki toistuu kaksi kertaa peräkkäin) “((.)\\3 )\\3” (luottokorttinumeron muodon tarkistus) Lukumäärät: esiintyy kerran (?), nolla tai useamman kerran (*), kerran tai useamman kerran (+), täsmälleen n kertaa {n}, vähintään n kertaa {n,}, vähintään n tai enintään m kertaa {n,m} Paikkamääreet: rivin alku (^), rivin loppu ($), sanan alku tai loppu (\\b), \\b negaatio (\\B), syötteen alku (\\A), syötteen loppu (\\z) 113 Esimerkki: säännöllinen lauseke public class SaannollinenLauseke { public static void main(String[] args) { // Luottokortin tarkistus String luottokortti = "1234 5678 9012 9876"; if (luottokortti.matches("\\d{4}( \\d{4}){3}")) System.out.println("kortti oikein"); else System.out.println("kortissa virhe"); // Päivämäärän tarkistus String pvm = "12.09.2011"; if (pvm.matches("(\\d{1,2}.){2}\\d{4}")) System.out.println("päivämäärä oikein"); else System.out.println("päivämäärässä virhe"); // Päivämäärän pilkkominen String[] sanat = pvm.split("\\."); for (int i=0; i<sanat.length; i++) System.out.println(sanat[i]); // Osamerkkijonon tarkistus String yhteys = "Puhelinnumeroni on 0500-123456 työpuhelimeen"; System.out.println("Tekstissä "+(yhteys.matches(".*[0-9]{2,}\\W\\d{4,}.*") ?"on puhelinnumero ":"ei ole puhelinnumeroa")); } } 114 Help • • • • • • Tutki merkkijonoja HELPistä String StringBuilder (StringBuffer) StringTokenizer Integer Is-alkuiset: isEmpty(), isAlphapetic(), isDigit(),... 115 Luentoharjoitus 16 Tulosta merkkijono käänteisenä. (7.3) 116 Luentoharjoitus 17 Laske syöttämäsi tekstin merkkien esiintymismäärät. a = 97 A = 65 z = 122 Z = 90 ä = 228 Ä = 196 å = 229 Å = 197 ö = 246 Ö = 214 117 Luentoharjoitus 18 Laadi ohjelma, joka tulostaa ryhmäsi opiskelijoiden nimet satunnaisjärjestyksessä. 118 Luentoharjoitus 19 Laadi henkilötunnuksen 1. muodon oikeellisuuden tarkistusohjelma 2. arvon oikeellisuuden tarkistusohjelma 3. sekä tulosta syntymäaika. (7.11) 119 Luentoharjoitus 20 Testaa, onko teksti ymmärrettävissä jos sekoitat seuraavasti. Sekoita tekstin jokaisen sanan merkit lukuunottamatta ensimmäistä ja viimeistä merkkiä.(7.14) 120 METODIT 121 Metodin muoto määreet palautetyyppi nimi (parametrit) { ohjelma } määreet Näkyvyys: public, private Luokka-/oliokohtaisuus (static) palautetyyppiPalautettavan arvon tyyppi on void jos ei palautettavaa arvoa parametrit Tyypit ja nimet muuttujille, jotka ottavat vastaan kutsussa annetut tiedot 122 Esimerkki (parametrit) public class Keskiarvo1 { public static void laskeKeskiarvo(int eka, int toka){ double c; c = (eka+toka)/2.0; System.out.println("Keskiarvo on "+c); } public static void main(String[] args){ int luku1, luku2; luku1 = Lue.koko("Anna luku1: "); luku2 = Lue.koko("Anna luku2: "); laskeKeskiarvo(luku1, luku2); } } 123 Esimerkki (palautearvo) public class Keskiarvo2 { public static double laskeKeskiarvo(int eka, int toka){ double c; public class Keskiarvo22 { c = (eka+toka)/2.0; public static double laskeKeskiarvo(int eka, int toka){ return c; return (eka+toka)/2.0; } } public static void main(String[] args){ public static void main(String[] args){ System.out.print("Anna luku1 ja luku2: "); int luku1, luku2; System.out.println("Keskiarvo on "+ double tulos1; laskeKeskiarvo(Lue.koko(), Lue.koko())); luku1 = Lue.koko("Anna luku1: "); } luku2 = Lue.koko("Anna luku2: "); tulos1 = laskeKeskiarvo(luku1, luku2); } System.out.println("Keskiarvo on "+tulos1); } } Javassa vain arvoparametreja (arvon kopiointi) 124 Esimerkki (taulukko) public class Taulukko1 { public static void rahaMuunnin(double[] rahaa){ for (int i=0; i<rahaa.length; i++) rahaa[i] /= 5.94573; } public static void main(String[] args){ double[] markat = {100,300,500,1000,1000000}; rahaMuunnin(markat); for (int i=0; i<markat.length; i++) System.out.println(markat[i]); } } Sama ”viitteen kopiointi” -periaate toimii muissakin olioissa. 125 Esimerkki (taulukko) public class Taulukko2 { public static double[] rahaMuunnin(double[] rahaa){ double[] muutettuRaha = new double[rahaa.length]; for (int i=0; i<rahaa.length; i++) muutettuRaha[i] = rahaa[i] / 5.94573; return muutettuRaha; } public static void main(String[] args){ double[] markat ={100,300,500,1000,1000000}; double[] uusiRaha; uusiRaha = rahaMuunnin(markat); for (int i=0; i<uusiRaha.length; i++) System.out.println((int)markat[i]+"\t\t= "+(int)uusiRaha[i]); } } 126 Esimerkki (vaihteleva) Vaihteleva määrä parametreja public class Vaihtuva { public static void main (String[] args){ int[] sarja = {3, 5, 7, 9}; int summa = yhteen(sarja); int tulo = kerro(3,5,7,9); System.out.println("Summa: "+summa); System.out.println("Tulo: "+tulo); } public static int yhteen (int[] sarja){ int summa = 0; for (int i=0; i<sarja.length; i++) summa += sarja[i]; return summa; } • samantyyppiset peräkkäiset parametrit voidaan ottaa vastaan metodissa sarjana • sarjaa käytetään kuten taulukkoa • sarjan oltava parametrilistan viimeisenä • vain yksi sarja metodissa public static int kerro (int ... luvut){ int tulo = 1; for (int i : luvut) // Huomaa uusi for tulo *= i; return tulo; } } 127 Esimerkki (kuormittaminen) public class Keskiarvo3 { private static double laskeKeskiarvo (double eka, double toka){ return (eka+toka)/2.0; } private static double laskeKeskiarvo (int eka, int toka, int kolmas){ return (eka+toka+kolmas)/3.0; } public static void main(String[] args){ int luku1, luku2, luku3; luku1 = Lue.koko("Anna 1. luku: "); luku2 = Lue.koko("Anna 2. luku: "); luku3 = Lue.koko("Anna 3. luku: "); System.out.println("Kolmen luvun keskiarvo on "+ laskeKeskiarvo(luku1, luku2, luku3)); System.out.println("Kahden luvun keskiarvo on "+ laskeKeskiarvo(luku1, luku2)); } 128 Esimerkki (rekursiivisuus) public class Rekursio{ public static void main(String[] args){ String teksti="DIPLOMI-INSINÖÖRI"; tulosta(teksti, 0); } public static void tulosta (String merkit, int i){ if (i < merkit.length()){ //pituus=17 System.out.print(merkit.charAt(i)); tulosta(merkit, i+1); System.out.print(merkit.charAt(i)); } } } 129 Luokkamuuttujat public class Luokkamuuttujat { private static int summa = 3; private static int kpl; public static void main(String[] args){ lisaa (4); tulosta(); poista (5); tulosta(); } private static void lisaa (int luku){ summa += luku; kpl++; } private static void poista (int luku){ summa -= luku; kpl++; } private static void tulosta (){ System.out.println("Summa: "+summa); System.out.println("Kappalemäärä: "+kpl); } } 130 Luentoharjoitus 21 Parametrit ja paluuarvo Tee metodi tutkiaksesi, montako satunnaislukua pitää luoda N:stä mahdollisesta ennen kuin tulee K samaa arvoa? • Montako kertaa noppaa pitää heittää ennen kuin tulee kaksi samaa numeroa? • Montako henkilöä pitää valita ennen kuin kahdella on sama syntymäpäivä? 131 Luentoharjoitus 22 Taulukko parametrina Tee taulukon sekoitusmetodi, joka sekoittaa saamansa taulukon mahdollisimman satunnaisesti ja nopeasti. Metodi palauttaa sekoitetun taulukon ja säilyttää alkuperäisen taulukon entisellään. Tulosta alkuperäinen ja sekoitettu taulukko tulosta-metodilla. 132 Luentoharjoitus 23 Valmiiden luokkien käyttö Alustus-metodi luo taulukon, jossa on miljoona satunnaista kokonaislukua. Lajittele-metodi lajittelee taulukon käyttäen Array-luokan sort-metodia. Sekoita-metodi sekoittaa taulukko. Mittaa metodien käyttämä aika Systemluokan currentTimeMillis-metodilla. Tulosta ajat. 133 Luentoharjoitus 24 Kuormittaminen Tee ”Laina”-luokka, jossa on kaksi ”lyhennys” -nimistä metodia. Toinen metodi saa lähtötietona velan määrän, vuosikoron ja maksuerän suuruuden. Toinen saa lähtötietona velan määrän, vuosikoron ja maksuerien määrän. Metodit tulostavat taulukon, jossa on lyhennystietoja lyhennyserittäin (velka, koron osuus, lyhennyksen osuus). 134 Luentoharjoitus 25 Luokkamuuttujat Keksi tekstin salakirjoitusmenetelmä, joka salaamisen lisäksi osaa myös avata salatun sanoman. 135 Alkulukujen ominaisuuksia • 2 on ainoa parillinen alkuluku • Mikään alkuluku kuin 5 ei pääty numeroon 5 • Alkulukujen 2,3,5,7 jälkeen kaikki alkuluvut päättyvät numeroihin 1,3,7,9 • Kahden alkuluvun tulo ei ole neliö • Jos alkulukuun, paitsi 2 ja 3, lisätään tai vähennetään 1 tulos on jaollinen luvulla 6 152
© Copyright 2025