Ohjelmointi 1, syksy 2007 -- Demo 8

Tehtävät julkaistaan:
 Maanantain luennolla 29.10.2007
Palautus viimeistään:
 6.11.2007 klo 18 (normaalisti tiistai-ilta)
100% tehtävistä tarkoittaa:
 5 kpl tehty

Tässä demossa on tehtävät jaettu kahteen tasoon. "Level 1" mahdollistaa perusasioita kertaavan lähestymisen. "Level 2" tarjoaa mahdollisuuden kokeilla laajempaa osaamista, jos perusasiat ovat hanskassa.

Jatkuvasti on tärkeätä käyttää aikaa miettimiseen ja etenkin sitten pyrkiä ymmärtämään mallivastauksista, miten homma olisi ollut mahdollista toteuttaa. Ja jos joku homma ei tunnu käyvän järkeen tai jos ei jotain ala osata soveltaa uuteen tilanteeseen, nyt on aika kysyä jokainen "tyhmältä tuntuva" mutta ei oikeasti tyhmä kysymys!

Contents

Yksinkertaisia ohjelmia

Back to basics; kerrataan yksinkertaisempia rakenteita.

Tehtävä 1:

Level1: Tee aliohjelmat, joiden rajapinta on seuraava:

public static String tekstiksiViikonpaiva(int vkp)

public static String tekstiksiKuukausi(int kk)

Näistä ensimmäinen palauttaa järjestysnumeroa vastaavan viikonpäivän merkkijonona, eli "maanantai", "tiistai" jne. Jälkimmäinen tekee saman kuukausille eli "tammikuu", "helmikuu".

Luonnollisesti teet testiohjelman, jossa kokeilet esim.:

System.out.println(tekstiksiKuukausi(11));
System.out.println(tekstiksiViikonpaiva(1));

Level 2: Jos perustoiminta oli sinulle helppo toteuttaa, lisää vielä poikkeuksen heitto, jos joku käyttää aliohjelmaasi väärin:

System.out.println(tekstiksiViikonpaiva(-4));

Soveltuva on Javan valmiin IllegalArgumentException -luokan poikkeus.

Tehtävä 2:

Level 1: Toteuta aliohjelma, jonka rajapinta on:

public static boolean onKarkausvuosi(int vuosi);

ja joka siis kertoo, onko parametrina annettu vuosi karkausvuosi. Karkausvuosi on neljällä jaollinen vuosi, paitsi 100 jaolliset vuodet ovat karkausvuosia vain jos ovat jaollisia myös 400:lla. Esim. 1900 ei ollut karkausvuosi, mutta 2000 oli.

Kokonaisluvun jaollisuuden voit tarkastaa modulo-operaattorilla "%", eli luku % jakaja == 0 pätee täsmälleen silloin kun luku on jaollinen jakajalla.

Level 2: Jos edellinen tuli helposti, tee myös aliohjelma, joka kertoo kuinka monta päivää on kuukaudessa, kun karkausvuosi otetaan huomioon. Siis parametrina on kuukausi ja vuosi kokonaislukuina, ja paluuarvona kokonaisluku, joka on päivien määrä. Helmikuu siis riippuu vuodesta ja muut ovat aina samoja.

Tehtävä 3:

Level 1: Tee ja testaile aliohjelma, joka tulostaa parametrina annetusta merkkijonosta joka toisen merkin. Ei saa kaatua tyhjän merkkijonon kohdalla.

Level 2: Jos tämä syntyi helposti, tee myös toinen aliohjelma, joka ottaa parametrina myös kokonaisluvun, joka kertoo kuinka monen merkin välein tulostetaan. Tämä aliohjelma ei saa tulostaa suoraan vaan täytyy palauttaa viite uuteen merkkijono-olioon, jossa on merkit sopivasti (mahdollisesti tyhjä jono).

Tiedostot vielä

Tehtävä 4: Satunnaisdatan generointi

Level 1: Tee aliohjelma, joka tekee liukulukutaulukon ja täyttää sen satunnaisilla lukuarvoilla. Taulukon koko pitää tulla parametrina.

Level 2: Tulosta luvut tekstimuodossa tiedostoon. Tiedoston nimi annettava parametrina aliohjelmalle.

Huomioitavaa:

  • luvut arvottava välille [-1,1[. Käytä Math.random()
  • parametriksi taulukon rivien ja sarakkeiden määrä
  • tallennuksessa parametriksi tiedoston nimi (testiohjelmassa voit kovakoodata kutsuun, mutta huomannet että aliohjelma toimisi tarvittaessa mille tahansa tiedostonimelle)
  • Tallennuksessa tulosta kaikki tarvittavat desimaalit mutta älä ylimääräisiä. double -tyyppisen liukuluvun esitystarkkuus on 17 kymmenjärjestelmän numeroa.
  • Kanoninen tapa tiedoston kirjoittamiselle löytyy esim. oppikirjan luvusta "20.1 Tietovirtaan kirjoittaminen" ja vastaavan näköisesti mistä tahansa lähteestä, joka puhuu Javan tiedostonkäsittelystä.

Javaa ja olioita

Tehtävä 5: Vertailtavat oliot, compareTo()

Tähän asti tuttua: olioluokalla on rajapinta eli julkisten metodien joukko. Javassa on mukana rajapinnan käsite: jos joku ominaisuus on yhteinen monelle eri luokalle, voidaan sitä vastaavista metodeista tehdä rajapinta (interface), jonka eri luokat toteuttavat, riippumatta luokitteluhierarkiasta. Yksi tärkeä rajapinta on nimeltään Comparable. Luokat, jotka toteuttavat tämän (määritelty implements Comparable), mahdollistavat olioyksilöidensä keskinäisen vertailun.

Level 1: Tee aliohjelma, joka ottaa parametrina kaksi String-merkkijonoa ja palauttaa niistä sen, joka on aakkosissa ensimmäisenä. Huomioitavaa:

  • String on Comparable eli rajapinnasta löytyy CompareTo -metodi. Linkki dokumentaatioon: http://java.sun.com/javase/6/docs/api/java/lang/String.html#compareTo(java.lang.String)
  • käytä nyt nimenomaan CompareTo -metodia, vaikka merkkijonossa olisi myös compareToIgnoreCase() joka jättää huomioimatta isot/pienet kirjaimet. Kyseinen on pelkästään merkkijonojen ominaisuus; CompareTo sen sijaan löytyy melkein kaikista luokista, joiden olioille voidaan järkevästi määritellä keskinäinen järjestys.

Level 2: Tee lisäksi aliohjelma, joka ottaa parametrina merkkijonotaulukon, ja palauttaa indeksin, josta taulukossa löytyy aakkosissa ensimmäisenä oleva merkkijono. Saat käyttää compareToIgnoreCase -metodia ja itse asiassa kannattanee soveltaa myös metodia trim() joka antaa merkkijonon ilman alussa ja lopussa mahdollisesti olevia tyhjämerkkejä.

Bonussektori

Tehtävä 6: BigInteger

Luokka java.math.BigInteger mahdollistaa tosi isojen kokonaislukujen käsittelyn. Muunna aiempi Fibonaccin lukujonon generointi palauttamaan BigInteger -luokan olio. Nyt pitäisi pystyä generoimaan hyvin isoja Fibonaccin lukuja ilman että lukualue pyörähtää yli. Primitiivimuuttujat eivät mahdollista tätä.

Mm. pankkijärjestelmässä on syytä käyttää tällaista oliota, jotta ei tule liukuluvuille ominaisia pyöristysvirheitä ja jotta ylivuodolta vältytään: euron tuhannesosan lisääminen tilille ei koskaan muuta saldoa negatiiviseksi miljardiksi, mikä on aina mahdollista primitiivimuuttujaa käytettäessä!

Tehtävä 7: Loogiset ja bittioperaatiot

Metodi java.lang.Integer.toBinaryString() palauttaa parametrina annetun kokonaisluvun biteiksi muunnettuna. Tee seuraavia kokeiluja, jotka auttavat ymmärtämään kokonaislukujen koodautumista koneeseen ja bittien käyttöä:

  • Tulosta luvut -17, -16, ... -1, 0, 1, ..., 17 bittijonoina. Luonnollisesti for-silmukkaa käyttäen...

  • Jokaisen luvun osalta tulosta myös vain kolme alinta bittiä. Tämä onnistuu biteittäisellä JA-operaatiolla. Eli luku & 7.

  • Tulosta kymmenjärjestelmässä luvut, jotka saat:

    1. siirtämällä bittejä yhdellä pykälällä vasemmalle. Eli operaatio luku << 1.
    2. siirtämällä bittejä kahdella pykälällä vasemmalle. Eli operaatio luku << 2.
    3. siirtämällä bittejä kahdella pykälällä vasemmalle. Eli operaatio luku << 3.

    Dokumentoi johonkin: Mitä huomaat tämän operaation matemaattisesta merkityksestä?

  • Kokeile myös siirtämistä oikealle kahdella eri tavoin:

    1. Operaattorilla >>
    2. Operaattorilla >>>

    Dokumentoi johonkin: Mistä tulosten erilaisuus johtuu?

  • Kokeile biteittäistä TAI-operaatiota: tulosta luvut seuraavien operaatioiden jälkeen:

    1. luku | 1
    2. luku | 2
    3. luku | 3

    Dokumentoi johonkin: Mitä siis voit tehdä operaattorilla | bittijonolle?

Tämän verran kokeiluja tällä erää. Pidemmällä tähtäimellä tulee vastaan sovelluksia biteittäisille operaatioille.