...
Code Block |
---|
| // fra http://en.wikipedia.org/wiki/Random_number_generation
public class RandomProgram1 {
// tilstand for tilfeldig tall-generatoren
long mw = 31;
long mz = 42;
long nextRandom() {
mz = 36969 * (mz & 65535) + (mz >> 16);
mw = 18000 * (mw & 65535) + (mw >> 16);
return (mz << 16) + mw;
}
void init() {
}
// tilstand for minimum
long min = Long.MAX_VALUE;
// tilstand for maksimum
long max = Long.MIN_VALUE;
// tilstand for gjennomsnitt
int count = 0;
long sum = 0;
void run() {
while (count < 1000) {
long randomValue = nextRandom();
if (randomValue < min) {
min = randomValue;
}
if (randomValue > max) {
max = randomValue;
}
sum += randomValue;
count++;
}
System.out.println("Min: " + min);
System.out.println("Max: " + max);
System.out.println("Average: " + (sum / count));
}
public static void main(String[] args) {
RandomProgram1 program = new RandomProgram1();
program.init();
program.run();
}
}
|
| De to første long-attributtene m_w og m_z er tilstand knyttet til tilfeldige tall-generatoren. For hvert nye tilfeldige tall som beregnes av nextRandom()-metoden, så oppdateres disse to attributtene. min- og max-attributtene holder henholdsvis hittil minste og hittil største verdi, og initialiseres til henholdsvis den største og minste mulige long-verdiene i Java. count- og sum-attributtene brukes for å beregne gjennomsnittet. init()-metoden er tom, siden den gjerne brukes til å konfigurere objekt(struktur)er og vi her ikke har noen objekter (bortsett fra hovedprogram-objektet). run()-metoden inneholder en løkke som går 1000 ganger. For hver runde så lager den et nytt tilfeldig tall med nextRandom()-metoden og oppdaterer min-, max-, sum- og count-attributtene. min oppdateres hvis den nye verdien er mindre, max oppdateres hvis den nye verdien er større og sum og count oppdateres alltid. Et objekttilstandsdiagram for klassen vil se slik ut: PlantUML Macro |
---|
object "RandomProgram1" as rp0 {
// tilstand for generator
mw = 31
mz = 42
// tilstand for minimum
min = 9223372036854775807
// tilstand for maksimum
max = -9223372036854775808
// tilstand for gjennomsnitt
count = 0
sum = 0
}
object "RandomProgram1" as rp1 {
// tilstand for generator
mw = 558000
mz = 101758174128
// tilstand for minimum
min = 101758174128
// tilstand for maksimum
max = 101758174128
// tilstand for gjennomsnitt
count = 1
sum = 101758174128
}
rp0 .right.> rp1: runde 1
object "RandomProgram1" as rp2 {
// tilstand for generator
mw = 606816008
mz = 101758174128
// tilstand for minimum
min = 101758174128
// tilstand for maksimum
max = 109923061745416
// tilstand for gjennomsnitt
count = 2
sum = 110024819919544
}
rp1 .right.> rp2: runde 2
object "RandomProgram1" as rp1000 {
// tilstand for generator
mw = 290483840
mz = 3057780577
// tilstand for minimum
min = 3057780577
// tilstand for maksimum
max = 158694648374228
// tilstand for gjennomsnitt
count = 1000
sum = 78963637600257262
}
rp2 .right.> rp1000: ... runde 1000
|
|
...
En ryddigere løsning er å dele problemet opp i mindre deler og la én klasse ta seg av hver del. Dette er grunnprinsippet i objektorientering: En klasse skal ha (kun) ett formål! Her er det naturlig å ha én klasse for tilfeldig tall-generatoren, én for å holde rede på minimumsverdien, én for å holde rede på maksimumsverdien og én for å håndtere gjennomsnittberegningen. Hver Siden hver av disse kun har ett formål og gjør én ting, så er det enkle å skrive.
Code Block |
---|
| public class RandomProgram2 {
Random random;
Min min;
Max max;
Average average;
void init() {
random = new Random();
min = new Min();
max = new Max();
average = new Average();
}
void run() {
for (int i = 0; i < 1000; i++) {
long randomValue = random.nextRandom();
min.accumulate(randomValue);
max.accumulate(randomValue);
average.accumulate(randomValue);
}
System.out.println("Min: " + min.getMin());
System.out.println("Max: " + max.getMax());
System.out.println("Average: " + average.getAverage());
}
public static void main(String[] args) {
RandomProgram2 program = new RandomProgram2();
program.init();
program.run();
}
} |
PlantUML Macro |
---|
object "RandomProgram2" as rp0 {
}
object "Random" as random0 {
mw = 31
mz = 42
}
object "Min" as min0 {
min = 9223372036854775807
}
object "Max" as max0 {
max = -9223372036854775808
}
object "Average" as average0 {
count = 0
sum = 0
}
rp0 -right-> random0: random
rp0 -right-> min0: min
rp0 -right-> max0: max
rp0 -right-> average0: average
object "RandomProgram1" as rp1 {
// tilstand for generator
mw = 558000
mz = 101758174128
// tilstand for minimum
min = 101758174128
// tilstand for maksimum
max = 101758174128
// tilstand for gjennomsnitt
count = 1
sum = 101758174128
}
rp0 .right.> rp1: runde 1
object "RandomProgram1" as rp2 {
// tilstand for generator
mw = 606816008
mz = 101758174128
// tilstand for minimum
min = 101758174128
// tilstand for maksimum
max = 109923061745416
// tilstand for gjennomsnitt
count = 2
sum = 110024819919544
}
rp1 .right.> rp2: runde 2
object "RandomProgram1" as rp1000 {
// tilstand for generator
mw = 290483840
mz = 3057780577
// tilstand for minimum
min = 3057780577
// tilstand for maksimum
max = 158694648374228
// tilstand for gjennomsnitt
count = 1000
sum = 78963637600257262
}
rp2 .right.> rp1000: ... runde 1000 |
| Code Block |
---|
| public class Random {
// from http://en.wikipedia.org/wiki/Random_number_generation
long mw = 31;
long mz = 42;
long nextRandom() {
mz = 36969 * (mz & 65535) + (mz >> 16);
mw = 18000 * (mw & 65535) + (mw >> 16);
return (mz << 16) + mw;
}
} |
Code Block |
---|
| public class Min {
long min = Long.MAX_VALUE;
public long getMin() {
return min;
}
void accumulate(long value) {
if (value < min) {
min = value;
}
}
} |
Code Block |
---|
| public class Max {
long max = Long.MIN_VALUE;
public long getMax() {
return max;
}
void accumulate(long value) {
if (value > max) {
max = value;
}
}
} |
Code Block |
---|
public class Average {
long count = 0, sum = 0;
long getAverage() {
return sum / count;
}
void accumulate(long value) {
sum += value;
count++;
}
} |
|
...