Satunnaisuus ohjelmissa
Satunnaisuutta tarvitaan esimerkiksi salausalgoritmeissa, koneoppimisessa sekä tietokonepelien ennustettavuuden vähentämisessä. Satunnaisuutta mallinnetaan käytännössä satunnaislukujen avulla, joiden luomiseen Java tarjoaa valmiin Random
-luokan. Random-luokasta voi tehdä olion jota voi käyttää seuraavalla tavalla.
import java.util.Random;
public class Arvontaa {
public static void main(String[] args) {
Random arpoja = new Random(); // luodaan apuväline arpoja
for (int i = 0; i < 10; i++) {
// Arvotaan ja tulostetaan satunnainen luku
int luku = arpoja.nextInt(10);
System.out.println(luku);
}
}
}
Yllä olevassa esimerkissä luodaan ensin Random
-luokasta olio. Random-olio tarjoaa metodin nextInt
, jolle annetaan parametrina kokonaisluku. Metodi palauttaa satunnaisen kokonaisluvun väliltä [0,kokonaisluku[
eli 0..(annettu kokonaisluku - 1).
Ohjelman tuottama tulostus ei ole aina sama. Yksi mahdollinen tulostusesimerkki on seuraava:
2 2 4 3 4 5 6 0 7 8
Metodin nextInt
avulla pystyy luomaan hyvin monipuolista satunnaisuutta. Ohjelmoija saattaisi esimerkiksi haluta, että ohjelman ilmoittama lämpötila on satunnainen ja väliltä [-30,50]. Tällöin ratkaisu on arpoa lukuja nollan ja kahdeksankymmenen väliltä ja miinustaa arvotusta luvusta 30.
Random arpoja = new Random();
int lampotila = arpoja.nextInt(81) - 30;
System.out.println(lampotila);
Random-luokasta tehdyn olion kautta päästään käsiksi myös satunnaisiin liukulukuihin, joita käytetään muunmuassa todennäköisyyslaskennan yhteydessä; tietokoneilla todennäköisyyksiä simuloidaan yleensä väliltä [0..1] olevilla luvuilla.
Random-oliolta satunnaisia liukulukuja saa metodilla nextDouble
. Tarkastellaan seuraavia säämahdollisuuksia:
- Sataa räntää todennäköisyydellä 0.1 (10%)
- Sataa lunta todennäköisyydellä 0.3 (30%)
- Aurinko paistaa todennäköisyydellä 0.6 (60%)
Luodaan edellä olevista arvioista sääennustaja.
import java.util.ArrayList;
import java.util.Random;
public class SaaEnnustaja {
private Random random;
public SaaEnnustaja() {
this.random = new Random();
}
public String ennustaSaa() {
double todennakoisyys = this.random.nextDouble();
if (todennakoisyys <= 0.1) {
return "Sataa räntää";
} else if (todennakoisyys <= 0.4) { // 0.1 + 0.3
return "Sataa lunta";
} else { // loput, 1.0 - 0.4 = 0.6
return "Aurinko paistaa";
}
}
public int ennustaLampotila() {
return (int) (4 * this.random.nextGaussian() - 3);
}
}
Metodi ennustaLampotila
on monella tapaa mielenkiintoinen. Metodin sisällä tehtävä kutsu this.random.nextGaussian()
on tavallinen metodikutsu, jonka kaltaisia olemme nähneet aikaisemminkin. Kiinnostavaa tässä Random
-luokan ilmentymän tarjoamassa metodissa on se, että metodin palauttama luku on normaalijakautunut (normaalijakautuneilla luvuilla voi kuvata esimerkiksi ihmisten pituuksia ja painoja — jos et koe mielenkiintoa satunnaisuuden eri lajeihin se ei haittaa!).
public int ennustaLampotila() {
return (int) (4 * this.random.nextGaussian() - 3);
}
Edellisessä esimerkissä käytetään eksplisiittistä tyyppimuunnosta liukulukujen muuntamiseen kokonaisluvuiksi (int)
. Vastaavalla menetelmällä voidaan muuttaa myös kokonaislukuja liukuluvuiksi kirjoittamalla (double) kokonaisluku
Luodaan vielä pääohjelma josta luokkaa SaaEnnustaja
käytetään.
// importit
public class Ohjelma {
public static void main(String[] args) {
SaaEnnustaja ennustaja = new SaaEnnustaja();
// tallennetaan päivät listalle
ArrayList<String> paivat = new ArrayList<>();
paivat.add("Ma");
paivat.add("Ti");
paivat.add("Ke");
paivat.add("To");
paivat.add("Pe");
paivat.add("La");
paivat.add("Su");
System.out.println("Seuraavan viikon sääennuste:");
for (String paiva: paivat) {
String saaEnnuste = ennustaja.ennustaSaa();
int lampotilaEnnuste = ennustaja.ennustaLampotila();
System.out.println(paiva + ": " + saaEnnuste + " " + lampotilaEnnuste + " astetta.");
}
}
}
Ohjelman tulostus voisi olla esimerkiksi seuraavanlainen:
Seuraavan viikon sääennuste: Ma: Sataa lunta 1 astetta. Ti: Sataa lunta 1 astetta. Ke: Aurinko paistaa -2 astetta. To: Aurinko paistaa 0 astetta. Pe: Sataa lunta -3 astetta. La: Sataa lunta -3 astetta. Su: Aurinko paistaa -5 astetta
Muistathan tarkistaa pistetilanteesi materiaalin oikeassa alareunassa olevasta pallosta!