Pakolliset tehtävät on merkitty harmaalla taustavärillä. Pakollisuus tarkoittaa, että kyseiset tehtävät ovat erityisen oleellisia ja niiden tekeminen on hyvin suositeltavaa. Jos joskus jokin "pakollinen" tehtävä jää tekemättä, kurssi ei kuitenkaan kaadu siihen.
Kotimaisten kielten tutkimuskeskus (Kotus) on julkaissut netissä suomen kielen sanalistan. Tässä tehtävässä käytetään listan muokattua versiota, jonka voit kopioida tästä.
Tallenna tiedosto NetBeans-projektisi päähakemistoon, jotta voit viitata siihen ohjelmassa suoraan nimellä "sanalista.txt". Päähakemisto on samanniminen kuin projektisi nimi.
Tee ohjelma, joka lukee tiedostossa olevat sanat ja tulostaa niiden määrän. Tässä vaiheessa sanoilla ei tarvitse tehdä mitään, riittää laskea niiden määrä.
Ohjelman tulostuksen tulisi olla seuraava:
Sanojen määrä: 91519
Tee ohjelma, joka tulostaa listan kaikki sanat, joissa on z-kirjain. Tällaisia sanoja ovat esimerkiksi jazz ja zombi.
Tee ohjelma, joka tulostaa listan kaikki sanat, jotka päättyvät l-kirjaimeen. Tällaisia sanoja ovat esimerkiksi kannel ja sammal.
Tee ohjelma, joka tulostaa listan kaikki sanat, jotka ovat palindromeja. Tällaisia sanoja ovat esimerkiksi ala ja enne.
Tee ohjelma, joka tulostaa listan kaikki sanat, jotka sisältävät kaikki suomen kielen vokaalit (aeiouyäö). Tällaisia sanoja ovat esimerkiksi myöhäiselokuva ja ympäristönsuojelija.
Keksi vielä jokin kiinnostava ominaisuus ja tee ohjelma, joka etsii listalta tämän ominaisuuden täyttävät sanat.
Ota pohjaksi viikon 1 tehtävän 4 luokkaa Sanakirja käyttävä sanakirjaohjelma. Voit käyttää pohjana myös täältä löytyvää mallivastausta.
Laajennetan sanakirjaa siten, että se lukee sanakirjan alustavan sisällön tiedostosta. Voit tehdä lukemisen erillisessä metodissa jota sanakirjan käyttäjä kutsuu:
public static void main(String[] args) { Sanakirja sanakirja = new Sanakirja("suomi-englanti.txt"); sanakirja.lataa(); // ohjelman päälogiikka (eli käännösten kysely ja uusien käännösten lisääminen) tänne // voit copypastata mallivastauksesta tai käyttää omaa versiotasi }
Tai vaihtoehtoisesti voit lukea sisällön jo konstruktorissa
Tiedoston nimi annetaan konstruktorin parametrina. Tiedosto koostuu tekstiriveistä jossa on sana-käännös-pareja:
olut beer apina monkey ohjelmoija programmer opiskelija student
Huom: jotta ohjelma löytää tiedoston, pitää se sijoittaa projektin juureen. Tämä onnistuu valitsemalla NetBeansista file -> new file -> other. Sanakirjaprojektin tulee olla pääprojektina kun luot tiedoston. Voit editoida tiedostoa joko NetBeansilla tai tekstieditorilla.
huom2: voit lukea syötteen kahdella tavalla, joko Scannerin metodilla next
yksittäinen sana kerrallaa tai nextLine
:llä rivi kerrallaan. Jos luet rivi kerrallaan, pitää rivi hajoittaa kahdeksi merkkijonoksi (esim. "olut beer" -> "olut", "beer") jotta lisäys sanakirjaan onnistuu. Tämä voidaan tehdä esim. split-komennolla:
String rivi = lukija.nextLine(); String[] osat = rivi.split(" "); // nyt osat[0] on rivin ensimmäinen sana ja osat[1] toinen
Tee sanakirjalle metodi talleta
, jota kutsuttaessa sanakirjan sisältö kirjoitetaan tiedostoon. Metodia on tarkoitus kutsua hieman ennen ohjelman lopetusta:
public static void main(String[] args) { Sanakirja sanakirja = new Sanakirja(); sanakirja.lataa(); // ohjelman päälogiikka sanakirja.talleta(); }
Talletus kannattanee hoitaa siten, että koko käännöslista kirjoitetaan uudelleen vanhan tiedoston päälle, eli materiaalissa esiteltyä append
-komentoa ei kannata käyttää.
Varmista että ohjelmasi toimii, eli että uuden käynnistyksen jälkeen edellisessä suorituksessa talletetut sanat löytyvät sanakirjasta.
Muokaa vielä ohjelmasi sellaiseksi, että se toimii vaikka käynnistettäessä sanakirjatiedostoa ei ole vielä olemassa. Voit poistaa sanakirjan esim. valitsemalla window -> files -> delete
Muokkaa viikolla 3 tekemääsi Käännöskonetta siten, että se käyttää muistavaa sanakirjaa.
Muokkaa käännöskonetta siten että se toimii seuraavan syötteen mukaan:
Anna lause: Tämä on kääntäjä käännös: this is compiler Anna lause: Tämä on ohjelma käännös: this is program Anna lause: Tuo on apina käännös: *** is *** Anna lause: Täma apina on kääntäjä käännös: this *** is compiler Anna lause: Tuntemattomat sanat: tuo apina
(sanakirjasta on ollut ainakin sanojen tämä, on, ohjelma, kaantaja käännökset)
Eli käännöksiä tehdään niin kauan kunnes käyttäjä antaa työhjän syötteen. Jos kääntäjä ei saa sanakirjan avulla selville jonkun sanan käännöstä, tulostuu sanan paikalle ***. Lopussa kääntäjä listaa kaikki syötteessä olleet tuntemattomat sanat. Huomaa että kahdessa lauseessa esiintynyt tuntematon sana ilmoitetaan tuntemattomaksi vaan kertaalleen.
Vihje: testaamisen helpottamiseksi "automatisoi" syöte tulemaan käyttäjän sijaan merkkijonosta. Tämä tapahtuu seuraavasti.
Lisää pääohejlmaasi seuraava metodi:
private static void asetaSyote() { String syote = "Tämä on kääntäjä.\n" + "Tuo on apina\n" + "Tämä on ohjelma\n" + "Tämä apina on kääntäjä\n" + "\n"; lukija = new Scanner(new ByteArrayInputStream(syote.getBytes()) ); }
Jokainen merkkijonon merkkeihin \n päättyvä rivi siis simuloi käyttäjän kirjoittamaa enterin painallukseen päättyvää koodiriviä.
Kutsu metodia pääohjelman alussa:
public static void main(String[] args) { asetaSyote(); Kaannoskone kaantaja = new Kaannoskone("suomi-englanti.txt"); // ... }
Kun haluat antaa syötteen itse, kommentoi metodikutsu.
Laajenna ohjelmaa siten, että ennen lopetusta kysytään tuntemattomaksi jääneille sanoille käännökset:
Anna lause: Tämä on kääntäjä käännös: this is compiler Anna lause: Tämä on ohjelma käännös: this is program Anna lause: Tuo on apina käännös: *** is *** Anna lause: Täma apina on kääntäjä käännös: this *** is compiler Anna lause: Tuntemattomat sanat: tuo apina Anna tuntemattomille käännökset: tuo, käännös: that apina, käännös: monkey
Käännöskone lisää uudet käännökset sanakirjaan. Koska sanakirja tallettaa käännökset tiedostoon, pitäisi uusien sanojen olla käännöskoneen repertuaarissa seuraavalla suorituskerralla. Varmista, että näin todellakin on.
Tyypillinen ominaisuus tietokonepelissä on ennätyslista. Tässä tehtäväsarjassa toteutetaan ennätyslista, joka tallennetaan tiedostoon.
Tämän tehtäväsarjan jälkeen puuttuu enää peli, johon ennätyslista liittyy. Sellainen tehdään heti ensi viikolla.
Ennätyslistan jokaisella rivillä on nimi ja pistemäärä. Lista on järjestetty pistemäärän mukaan suurimmasta pienimpään. Listan koko on kiinteä (esim. 10 ennätystulosta).
Seuraavassa on ennätyslista, jonka koko on 5 ja jossa on 2 tulosta:
nimi | pistemäärä |
Pekka M. | 5000 |
Antti L.. | 1000 |
-- | 0 |
-- | 0 |
-- | 0 |
Tee luokka Ennatyslista
ja
lisää siihen seuraavat metodit:
tyhjenna
,
joka laittaa listan kaikkiin kohtiin
nimeksi -- ja pistemääräksi 0
toString
,
joka tuottaa listasta järkevän merkkijonoesityksen
Seuraava ohjelma testaa ennätyslistan toimintaa:
public class Main { public static void main(String[] args) { Ennatyslista lista = new Ennatyslista(5); lista.tyhjenna(); System.out.println(lista); } }
Ohjelman tulostuksen tulisi olla seuraava:
-- 0 -- 0 -- 0 -- 0 -- 0
Lisää ennätyslistaan metodi lisaaTulos
,
jonka avulla siihen voi lisätä tuloksen.
Tuloksen täytyy mennä oikeaan paikkaan listassa
ja syrjäyttää listan viimeinen tulos.
Jos tulos on liian huono, se ei pääse listalle.
Seuraava ohjelma testaa metodia:
Seuraava ohjelma testaa ennätyslistan toimintaa:
public class Main { public static void main(String[] args) { Ennatyslista lista = new Ennatyslista(5); lista.tyhjenna(); lista.lisaaTulos("AAA", 5000); lista.lisaaTulos("BBB", 2000); lista.lisaaTulos("CCC", 3000); lista.lisaaTulos("DDD", 1000); lista.lisaaTulos("EEE", 6000); lista.lisaaTulos("FFF", 4000); System.out.println(lista); lista.lisaaTulos("GGG", 7000); lista.lisaaTulos("HHH", 3500); System.out.println(lista); } }
Ohjelman tulostuksen tulisi olla seuraava:
EEE 6000 AAA 5000 FFF 4000 CCC 3000 BBB 2000 GGG 7000 EEE 6000 AAA 5000 FFF 4000 HHH 3500
Lisää ennätyslistaan metodi tallenna
,
joka tallentaa ennätyslistan annettuun tiedostoon.
Valitse tiedostolle järkevä rakenne.
Esimerkiksi voit tallentaa ensimmäiselle riville listan koon
ja sitten omille riveilleen kunkin nimen ja pistemäärän.
Testaa myös, että tallennusmetodi toimii.
Lisää ennätyslistaan metodi lataa
,
joka lataa ennätyslistan annetusta tiedostosta.
Testaa myös, että latausmetodi toimii.
Jos ennätykset tallentaa sellaisenaan tiedostoon, ongelmaksi tulee, että epärehellinen pelaaja voi muokata ennätyksiä mielensä mukaan.
Suunnittele ja toteuta tapa, joka estää keskivertopelaajaa huijaamasta muuttamalla ennätystiedostoa.
Ohjelmoiniin perusteiden viikolla 5 toteutettiin kivi-paperi-sakset-peli. Toteutamme tässä tehtävässä KPS:stä sekä kaksin- että yksinpelin. Käytämme osittain valmista koodia toteutuksemme apuna.
Oli kyseessä yksin- tai kaksinpeli, noudattaa KPS samaa kaavaa. Peli koostuu pelikierroksista, ja jokaisen kierroksen aikana
Jos pelataan tietokonetta vastaan, esim. "pelaaja 2" onkin tekoäly.
Itseasiassa myös viimeviikkoinen tikkupeli etenee saman kaavan mukaan.
Seuraavassa on valmiiksi toteutettu yksinkertaisten kaksinpelien toteuttamiseen tarkoitettu "pelikehys":
import java.util.Scanner; public abstract class Pelikehys { protected int ykkosenVoitot; protected int kakkosenVoitot; protected int tasapelit; protected int kierrokset; private Scanner lukija = new Scanner(System.in); /** * Metodia kutsuttaessa pelataan yksi kierros. Metodi * palauttaa true jos kumpikaan pelaaja ei halunnut lopettaa. * * Kierroksen toiminnallisuus määritellään aliluokassa syrjäyttämällä * pelaaKierros-metodin kutsumat abstraktit ja tyhjät metodit. */ public boolean pelaaKierros(){ tulostaOhje(); String eka = ekanVastaus(); if ( lopetuksenTarkastus(eka) ) return false; String toka = tokanVastaus(); if ( lopetuksenTarkastus(toka) ) return false; int voittaja = selvitaVoittaja(eka, toka); if ( voittaja==1 ) ykkosenVoitot++; else if ( voittaja==2 ) kakkosenVoitot++; else tasapelit++; kierrokset++; tulostaKierroksenTiedot( voittaja ); if ( jokaKierroksellaStatistiikka() ) tulostaStatistiikka(); return true; } /* * metodi, joka on pakko ylikirjoittaa: * * palauttaa 1 jos voittaja on pelaaja 1 * 2 jos voittaja on pelaaja 2 * jonkun muun luvun tasapelin tapauksessa */ public abstract int selvitaVoittaja(String eka, String toka); // Oletustoiminnallisuudet, jotka SAA ylikirjoittaa aliluokassa. // tulostaa joka kierroksella ohjeen pelaajille public void tulostaOhje() { } // palauttaa ensimmäisen pelaajan vastauksen public String ekanVastaus(){ System.out.print( pelaaja1() +":n vastaus: "); return lukija.nextLine(); } // palauttaa toisen pelaajan vastauksen public String tokanVastaus() { System.out.print( pelaaja2() +":n vastaus: "); return lukija.nextLine(); } // palauttaa true jos pelaajan syöte on ilmaisee pelin lopetuksen public boolean lopetuksenTarkastus(String syote) { return syote.equals(""); } // palauttaa true jos joka kierroksella halutaan tulostaa tilastotietoja public boolean jokaKierroksellaStatistiikka() { return true; } // tulostaa pelikierroksen tuloksen public void tulostaKierroksenTiedot(int voittaja) { if ( voittaja==1 ) System.out.println("voittaja "+ pelaaja1()); else if ( voittaja==2 ) System.out.println("voittaja "+ pelaaja2()); else System.out.println("tasapeli"); } // tulostaa tilastotiedot public void tulostaStatistiikka() { System.out.println( "kierroksia " +kierrokset ); System.out.println( pelaaja1()+" - "+pelaaja2()+ " " + ykkosenVoitot+ "-"+kakkosenVoitot ); } // pelaajien nimet voidaan vaihtaa ylikirjoittamalla seuraavat public String pelaaja1(){ return "pelaaja 1"; } public String pelaaja2(){ return "pelaaja 2"; } }
Kuten näemme Pelikehys
on abstrakti luokka, eli jotta siitä voitaisiin luoda olio, on luokka perittävä ja luokassa oleva abstrakti metodi on pakko ylikirjoittaa.
Pelikehyksen toimintaperiaatteen ymmärtäminen voi olla aluksi hankalaa. Kehyksen käyttö on kuitenkin helppoa kun periaateen ymmärtää.
Luodaan kehyksen avulla yksinkertainen arvauspeli. Jokaisella kierroksella molemmat pelaajat kirjoittavat jonkun sanan. Se kumman sana oli pitempi, voittaa pelin.
Pelin toteuttava luokka ArvausPeli perii luokan Pelikehys. ArvausPelin tulee ylikirjoittaa Pelikehyksen abstrakti metodi selvitaVoittaja
. Nimensä mukaisesti metodi määrittelee, yhden pelikierroksen voittajan:
public class ArvausPeli extends Pelikehys { // palauttaa 1 jos voittaja on pelaaja 1 (parametri eika) // 2 jos voittaja on pelaaja 2 (parametri toka) // jonkun muun luvun tasapelin tapauksessa public int selvitaVoittaja(String eka, String toka) { if ( eka.length() > toka.length() ) return 1; else if ( eka.length() < toka.length() ) return 2; return 0; } }
Kehyksessä on paljon muitakin metodeja joita ylikirjoittamalla voi säädellä pelin toimintaa. Muita metodeja ei kuitenkaan ole pakko ylikirjoittaa.
Monesta arvauskierroksesta koostuva peli muodostuu seuraavasta pääohjelmasta:
public static void main(String[] args) { ArvausPeli peli = new ArvausPeli(); while ( true ){ boolean eiLopeteta = peli.pelaaKierros(); if ( eiLopeteta==false ) break; } System.out.println("\nlopetetaan"); peli.tulostaStatistiikka(); }
Muuta peliä siten, että pääohjelmassa ensin kysytään pelaajien nimet. Nimet annetaan ArvausPeli:lle konstruktorin parametrina:
public static Scanner lukija = new Scanner(System.in); public static void main(String[] args) { System.out.println("Pelaajien nimet: "); String pelaaja1 = lukija.nextLine(); String pelaaja2 = lukija.nextLine(); ArvausPeli peli = new ArvausPeli(pelaaja1, pelaaja2); while ( true ){ boolean eiLopeteta = peli.pelaaKierros(); if ( eiLopeteta==false ) break; } System.out.println("\nlopetetaan"); peli.tulostaStatistiikka(); }
Ohjelman tulee nyt tulostaa pelaajien nimet:
Pelaajien nimet: Pekka Antti Pekka:n vastaus: tietokone Antti:n vastaus: algoritmi tasapeli kierroksia 1 Pekka - Antti 0-0 ...
Saat muutoksen aikaan tekemällä ArvausPeli:lle sopivan konstruktorin ja ylikirjoittamalla metodit
pelaaja1()
ja pelaaja2()
sopivalla tavalla.
Oletusarvoisesti peli lopetetaan jos jompi kumpi pelaajista antaa tyhjän syötteen. Muuta peliä siten, että peli voidaan lopettaa aikaisintaan kolmen pelikierroksen jälkeen. Jälleen muutos edellyttää tietyn metodin ylikirjoittamista. Etsi koodista oikea metodi ja tee muutos.
Toteuta kahden ihmispelaajan vastakkainen KPS käyttäen pelikehystä.
Pelin tulostusten pitäisi näyttää suunilleen seuraavalta
.Pelaajien nimet: Pekka Juhana Pekka:n vastaus: k Juhana:n vastaus: p voittaja Juhana kierroksia 1 Pekka - Juhana 0-1 Pekka:n vastaus: p Juhana:n vastaus: s voittaja Juhana kierroksia 2 Pekka - Juhana 0-2
Toteuta yksinpeli tekoälyä vastaan.
Koska kierroksen voittajan selvityslogiikka on sama kuin kaksinpelissä, kannattaa yksinpelin pelikierroksen toteutus periä kaksinpelistä (joka siis perii pelikehyksen). Tekoäly tulee nyt pelaajaksi 2, joten joudut ylikirjoittamaan metodin tokanVastaus
pyytämään tuloksen tekoälyltä. Voit käyttää esim. seuraavaa yksinkertaista tekoälyä:
import java.util.Random; public class YksinkertainenTekoaly { private Random random = new Random(); public String teeSiirto() { int arpa = random.nextInt(3); if ( arpa==0 ) return "k"; else if ( arpa==1 ) return "p"; else return "s"; } }
Pelin tulisi näyttää seuraavalta:
Pelaajan nimi: Esko Esko:n vastaus: k tekoälyn siirto: s voittaja Esko kierroksia 1 Esko - tekoäly 1-0 Esko:n vastaus: k tekoälyn siirto: k tasapeli kierroksia 2 Esko - tekoäly 1-0
Muuta ohjelmasi käyttämään Ohpen viikon 5 tehtävässä 6.5 tehtyä muistavaa tekoälyä. Jos et ole tehnyt tehtävää tai kadotit oman muistavan tekoälysi, voit käyttää mallivastauksen muistavaa tekoälyä.
Tässä tehtäväsarjassa toteutetaan muutama iteraattori.
HUOM: Voit jättää kaikissa tehtävissä Iterator
-rajapinnan
vaatiman remove()
-metodin tyhjäksi.
Tehdään iteraattori, joka käy läpi annetu kokonaislukuvälin.
Tee luokka LukuvaliIteraattori
, joka toteuttaa rajapinnan
Iterator<Integer>
. Luokan konstruktori ottaa kaksi
int
-parametria: ensimmäisen ja viimeisen läpi käytävän luvun.
Iteraattoria voi testata seuraavalla pääohjelmalla:
Iterator<Integer> i = new LukuvaliIteraattori(4, 12); while (i.hasNext()) { System.out.print(i.next() + " "); } System.out.println();
Tulostus:
4 5 6 7 8 9 10 11 12
Tehdään iteraattori, joka käy läpi merkkijonon jokaisen merkin.
Tee luokka MerkkiIteraattori
, joka toteuttaa rajapinnan
Iterator<Character>
.
Luokan konstruktori ottaa läpikäytävän merkkijonon.
Iteraattoria voi testata seuraavalla pääohjelmalla:
Iterator<Character> i = new MerkkiIteraattori("Pingviini"); while (i.hasNext()) { System.out.print(i.next() + " "); } System.out.println();
Tulostus:
P i n g v i i n i
Sivuhuomautus:
Kuten arvata saattaa, Character
on char
-tyyppiä
vastaava oliotyyppi (vrt. Integer
ja int
).
Luokkien tyyppiparametreiksi (< ... >
)
voidaan laittaa vain oliotyyppejä, mutta Java kyllä tekee muunnoksen
alkeistyyppien ja vastaavien oliotyyppien välillä automaattisesti
tarpeen mukaan.
Iteraattoria ei suoraan voi käyttää foreach-tyyppisessä
for (Tyyppi alkio : kokoelma)
-silmukassa.
Foreach vaatii kokoelmaksi Iterable
-rajapinnan toteuttavan olion.
Esimerkiksi vanha tuttu ArrayList
toteuttaa Iterable
n.
Tehdään iteraattoreitamme varten seuraava yleinen Iterable
n
toteutus:
public class IteroitavaIteraattori<T> implements Iterable<T> { private Iterator<T> iteraattori; public IteroitavaIteraattori(Iterator<T> iteraattori) { this.iteraattori = iteraattori; } public Iterator<T> iterator() { return iteraattori; } }
Nyt iteraattoreitamme voisi periaatteessa käyttää seuraavasti:
for (char merkki : new IteroitavaIteraattori<Character>(new MerkkiIteraattori("Pingviini"))) { System.out.print(merkki + " "); } System.out.println();
Hyi! Tehdään tästä vähän vähemmän rumaa kätevillä apumetodeilla.
Tee luokka Iteraattorit
, ja lisää sinne sopivat
staattiset metodit lukuvali
ja merkit
niin,
että seuraava pääohjelma toimii.
for (int luku : Iteraattorit.lukuvali(3, 7)) { System.out.print(luku + " "); } System.out.println(); for (char merkki : Iteraattorit.merkit("Pingviini")) { System.out.print(merkki + " "); } System.out.println();
Tulostus:
3 4 5 6 7 P i n g v i i n i
Tee iteraattoriluokka KaanteinenIteraattori
,
joka käy läpi konstruktorissa annetun ArrayList
:n alkiot
käänteisessä järjestyksessä lopusta alkuun.
Halutaan, että iteraattori toimii kaikille ArrayList
eille
alkion tyypistä riippumatta. Iteraattori täytyy siis tehdä
tyyppiparametroitavaksi seuraavasti:
public class KaanteinenIteraattori<T> implements Iterator<T> { // ... public KaanteinenIteraattori(ArrayList<T> lista) { // ... } // ... }
Nyt iteraattori toimii kaikilla tyypeillä T
.
Iteraattorista voi luoda vaikkapa merkkijonoilla toimivan ilmentymän seuraavasti.
ArrayList<String> sanalista = ...; KaanteinenIteraattori<String> i = new KaanteinenIteraattori<String>(sanalista);
Perehdymme tällaisiin useilla tyypeillä toimiviin "geneerisiin" luokkiin tarkemmin myöhemmin.
Iteraattorit
-luokkaan tuleva staattinen metodi tarvitsee nyt
myös tyyppiparametrin. Metodi näyttää seuraavalta:
public static <T> Iterable<T> kaannettyna(ArrayList<T> lista) { // ... }
Kaiken tämän jälkeen seuraavan pääohjelman pitäisi toimia:
ArrayList<String> sanoja = new ArrayList<String>(); sanoja.add("hei"); sanoja.add("hoi"); sanoja.add("hui"); ArrayList<Integer> lukuja = new ArrayList<Integer>(); lukuja.add(43); lukuja.add(84); lukuja.add(19); lukuja.add(57); for (String sana : Iteraattorit.kaannettyna(sanoja)) { System.out.print(sana + " "); } System.out.println(); for (int luku : Iteraattorit.kaannettyna(lukuja)) { System.out.print(luku + " "); } System.out.println();
Tulostus
hui hoi hei 57 19 84 43
P.S. Voit halutessasi toteuttaa myös remove()
-metodin,
jonka tarkoitus on poistaa kokoelmasta next()
:llä
viimeeksi haettu alkio.
Luonteva tapa tallentaa kokonaisluku Javassa
on käyttää int
- tai long
-muuttujaa.
Ongelmaksi voi kuitenkin tulla,
että luku on liian suuri eikä se mahdu muuttujaan.
Jos käytössä on int
-muuttuja,
sallittu lukualue on -2^31 ... 2^31-1,
ja jos käytössä on long
-muuttuja,
sallittu lukualue on -2^63 ... 2^63-1.
Yksi ratkaisu ongelmaan on tallentaa luvut merkkijonoina, jolloin niiden pituutta ei ole rajoitettu. Tällöin kuitenkaan Javan tavalliset laskutoimitukset (+, * ym.) eivät sovellu lukujen käsittelyyn vaan niitä varten pitää toteuttaa omia metodeita.
Toteuta metodit summa
ja tulo
,
jotka laskevat kahden merkkijonomuotoisen
ei-negatiivisen kokonaisluvun summan ja tulon.
Seuraava ohjelma testaa metodeita:
public class SuuretLuvut { public static void main(String[] args) { String luku = "123456789123456789123456789"; System.out.println("Summa: " + summa(luku, luku)); System.out.println("Tulo: " + tulo(luku, luku)); } }
Ohjelman tulisi tuottaa seuraava tulostus:
Summa: 246913578246913578246913578 Tulo: 15241578780673678546105778281054720515622620750190521
Käytännössä suurten lukujen käsittelyn
toteuttaminen yllä olevalla tavalla olisi hankalaa.
Javassa onkin myös valmis BigInteger
-luokka
suurten kokonaislukujen käsittelyyn.
Etsi luokasta tietoa Googlella ja toteuta sen avulla
edellisen tehtävän ohjelma.