Arpoo pisteitä neliönmuotoiselle alueelle, katsoo kuuluuko arvottu piste ympyrän sisälle ja laskee näiden arpomalla saatujen tietojen perusteella piin likiarvoa.
Tämä metodi ei ole kovinkaan tarkka, eikä nopea, mutta onpahan kuitenkin... :)
EDIT: Koodia muutettu siten, että sen saa nyt myös pysäytettyä, eli nyt se ei edes jää jumiin (lue kommentit jos haluat tietää mitä se teki ennen...)
Valmis appletti on osoitteessa http://www.paivola.net/~sami/java/pii/pii.html
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Pii extends Applet implements ActionListener {
//Laskurit laskemaan sisälle ja ulos osuneita pisteitä
int sisalla, ulkona;
int arvottu;
boolean stopped;
Button stop;
//Tekstikenttä likiarvon tulostamista varten
Label pii;
public void init() {
//Koon asettaminen ja laskurien alustaminen
//Laskennan kannalta koko on samantekevää,
//mutta alueen pitää olla neliön muotoinen!
this.setSize(500, 500);
sisalla = 0;
ulkona = 0;
arvottu = 0;
pii = new Label();
add(pii);
//Piirtämisen pysäyttämiseen
stopped = false;
stop = new Button("stop/resume");
add(stop);
stop.addActionListener(this);
}
//Pysäytetään/jatketaan nappulaa painettaessa
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(stop)) {
stopped = !stopped;
repaint();
}
}
//Ylikirjoitetaan update, jotta vanhat tavarat eivät pyyhkiytyisi pois
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
//Asetetaan tekstikenttä ja nappula sopivan kokoiseksi
pii.setBounds(this.getWidth() / 2 - 75, 10, 150, 20);
stop.setBounds(this.getWidth() / 2 - 40, 40, 80, 20);
//Pyöritään silmukassa koko loppuelämä... Tai kunnes painetaan stop
if (!stopped) {
//Arvotaan uusi piste
double x = Math.random() * this.getWidth();
double y = Math.random() * this.getHeight();
//Jos piste on alueen sisällä, maalataan se punaisella,
//ulkopuolella olevat pisteet maalataan vihreällä
if (onkoSisalla(x, y)) {
int red, green, blue;
red = (int)(Math.random() * 100) + 155;
green = (int)(Math.random() * 100);
blue = (int)(Math.random() * 100);
g.setColor(new Color (red, green, blue));
} else {
int red, green, blue;
red = (int)(Math.random() * 100);
green = (int)(Math.random() * 100) + 155;
blue = (int)(Math.random() * 100);
g.setColor(new Color (red, green, blue));
}
//Piirretään piste
g.drawLine((int)x, (int)y, (int)x, (int)y);
arvottu++;
//Näytetään piin arpomalla saatu likiarvo 10000 kierroksen välein
//sekä konsolissa, että piirtopinnalla
if (arvottu % 10000 == 0) {
System.out.println((4.0 * sisalla) / (double)arvottu);
pii.setText("" + (4.0 * sisalla) / (double)arvottu);
}
repaint();
}
}
//Metodi, joka tarkistaa kuuluuko piste ympyrän sisälle vai ei.
//Laskemiseen käytetään perinteistä Pythagoraan lausetta, eli
//a^2 + b^2 = c^2
public boolean onkoSisalla(double x, double y) {
if (Math.sqrt(Math.pow(((this.getWidth() / 2) - x), 2)
+ Math.pow(((this.getHeight() / 2) - y), 2))
< this.getHeight() / 2) {
sisalla++;
return true;
} else {
ulkona++;
return false;
}
}
}Vielä yksi pikkujuttu:
Kannattaa varoa hieman (tai ainakin olla tietoinen tästä asiasta), sillä tuo ikuinen silmukka saattaa aiheuttaa selaimen jämähtämisen appletin katsomisen jälkeen (selain saattaa kuluttaa yhä melkein 100% prosessoriajasta), mutta selaimen uudelleen käynnistäminen auttaa jos näin käy.
Tässä on vähän samantyylinen QBasic-ohjelma, tosin ilman grafiikkaa.
RANDOMIZE TIMER
FOR i& = 1 TO 2147483647
IF SQR(RND ^ 2 + RND ^ 2) < 1 THEN
j& = j& + 1
END IF
LOCATE 1, 1: PRINT j& / i& * 4
NEXTToinen varoitus:
Minulla se ainakin jatkoi kuvan piirtämistä näytölle
vaikka selaimen sulkikin. Ja aina kun avasi jonkun
ponnahdusikkunan(esim. käynnistä-valikon), niin se piirti
sen päälle (vaikka se on eri kohdassa kuin appletti oli).
Siitä ei selvinnyt muuta kuin reset-napilla.
Minulla näkyy pelkkää harmaata(IE6, Java 1.4).
Tuolla appletti -linkissä
ezuli:
Aika mielenkiintoinen "feature"... Mutta luultavasti prosessin tappaminen lopettaisi sen piirtämisen. (Toisaalta eikös appletien ainakin pitäisi olla melko turvallisia suorittaa ilman sivuvaikutuksia?)
No just... kivoja ohjelmia kun kone menee tileen, ja minä menin avaamaan sen >:P
Poistakaa tuo linkki ettei muille käy samoin.
Linkki käännettyyn appletiin on
http://www.paivola.net/~sami/java/pii/pii.html
Ja muistithan lukaista ne pari pikkujuttua, mitä tämän kanssa on käynyt... ;)
Eikös kannattaisi tehdä vaikka silleen, et se kysyy kuinka monta desimaalia siihen haluaa...
Aika hyvä.
Pienen odottelun jälkeen 4 ensimmäistä desimaalia ovat oikein.
Heh nää koulun kirjaston 200mhz koneet tilttaa hyvin tällä :D
Ei se prosessi näkynyt koneella enää missään, ainakaan ctr+alt+del valikossa. Katsoin applettia n.2min ja odotin sammuttamisen jälkeen 5min, jonka jälkeen resettasin. Eli se luultavasti täyttää koneen muistin piirto käskyillä.
Siihen kannattaisi kyllä lisätä joko piste rajoitus, tai odotus käsky, ettei se anna koneelle enempää tekemistä kuin se ehtii tehdä.
'Varoitus' tai jotain jos on huono jäähdytin niin silloin ei ainakaan kannata kokeilla vielä tarkempia arvoja...
Ati Radeon (en muista mikä) ilman jäähdytintä 6 min. ja Ylikuumeni...
Unohdin sanoa: laski piin tarkkaa arvoa ilman takarajaa...
Ilmeisesti tähän oli todellakin syytä tehdä jonkinlainen pysäytys, jollaisen lisäsinkin siihen äsken...
Ja vielä kerran voisin pyytää anteeksi niitä muutamaa kaatunutta konetta, jotka tämä aiheutti ;)
Aihe on jo aika vanha, joten et voi enää vastata siihen.