ich soll ein Würfel 6000000 würfeln und die Werte in einem Array speichern aber wie (totaler Java Anfänger)?

5 Antworten

6 Millionen? Das wird schwierig in einem Array. Benutze Bytes, oder besser: Zähle die Statistiken während der Schleife!

Für ein int braucht Java 32 bits, für ein Byte nur 8.

0

wieso?
6mio * 4bytes macht 24Mb.
Als ich noch jung war, war das ein Problem. Heute nicht mehr ;-D

1

Mir ist zwar der Sinn dieser Aufgabe nicht bekannt, aber ich könnte mir vorstellen, dass man damit beweisen will, dass man per Programm keine Zufallszahlen erstellen kann. Warum das so ist, ist ganz einfach: Für die Erstellung einer echten Zufallszahl gibt es keinen Algirithmus. Denn jeder wie auch immer geartete Algorithmus würde bei einer Wiederholung immer die gleiche Zahl liefern. Man benötigt einen externen Vorgang, bei dem man zufällig anfallende Zahlen abgreifen kann. Das wäre z.B. der Timer, bei dem man zumindest beim erstenmal eine echte Zufallszahl bekommt. Alle nachfolgenden Zahlen stehen mit den vorangegangen Zahlen im Zusammenhang, wenn kein von außen kommendes Ereignis die Regelmäßigkeit stört. Das könnten parallel laufende Programme sein oder manuelle Eingaben per Tastendruck. Wäre bei einem Neustart des Programmes die erste Zahl gleich einer Zahl aus einem vorangegangenen Lauf, so wären ab dieser Stelle alle folgenden Zahlen ebenfalls gleich. Dagegen gibt es ungewollte Beeinflussung des Programmlaufes, etwa durch parallel laufende andere Programme, die die Laufzeit beeinflussen. In den 70ger Jahren hat IBM Laborversuche gemacht, um aus dem atmosphärischen Rauschen echte Zufallszahlen zu erzeugen, z.B. zum Testen von Rechnerschaltungen und statistischen Verfahren.

Für die praktische Anwendung werden echte Zufallszahlen durch scheinbare Zufallszahlen ersetzt. Man kann mittels Algorithmen Zahlen so bearbeiten, dass ihre Folge auf Anhieb keine erkennbare Regelmäßigkeit zeigt. Für viele Anwendungen ist das ausreichend.

Das Problem bei Deinem Programm wäre, dass die Programmschleife, die die Zufallszahlen erzeugt, in weitgehend regelmäßigem Abstand auf die Randomanweisung des Systems trifft, was eine unerwünschte Regelmäßigkeit bedeutet. Würde man für jeden Schleifendurchlauf eine Unterbrechung einbauen, die per Tastendruck wieder aufgehoben wird, bekäme man echte Zufallszahlen. Bei 6 Mio Zahlen wäre das sicher kein leichtes Unterfangen.

Auch wenn diese Antwort schon drei Jahre alt ist, sollte sie nicht unwidersprochen stehen bleiben. Da hat sich jemand viel Mühe gemacht um eine Menge Unsinn zusammenzuschreiben.

Die einzig richtige Aussage ist: Man kann per Algorithmus keine echten Zufallszahlen sondern nur Pseudozufallszahlen erzeugen.

Mit obigem Programm könnte man nicht zeigen, dass die Zahlen nur pseudozufällig sind.

Der Randomgenerator aus der Java-Bibliothek liefert gleichverteilte Zufallszahlen die auf den Bereich 0 bis 1 normiert sind. Die Periode beträgt etwa 2^48, das sind 281 Billionen. Mit jeder Abfrage des Randomgenerators gibt es eine neue Zahl, die nur von der vorherigen Zahl abhängt. Nicht von der seit der letzten Abfrage vergangenen Zeit, so dass man da keine Unterbrechung einbauen muss.

Der Algorithmus ist sehr einfach:

seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)

wobei seed beim Programmstart einmalig aus der Uhrzeit erzeugt wird.

Die Güte des Zufallszahlengenerators ist für Simulationen ausreichend, aber z.B. nicht zur Erzeugung hochsensibler Passwörter.

0
@Schachpapa

Wo siehst Du jetzt den Widerspruch, den Du anfangs angekündigt hast, oder anders, wo ist bei meinem Posting was falsch? Es würde mich schon interessieren. Ich habe schon öfter Programmroutinen programmieren müssen, wo ich mich mit solchen Problemen beschäftigen musste und bin eigentlich mit der Materie vertraut. Ich bin aber noch lernfähig.

0
@wotan38

Ich nehme die Formulierung "eine Menge Unsinn" zurück. Ich habe mich im Ton vergriffen, Entschuldigung.

An deinem Posting stimmt nicht, dass man mit 6 Millionen pseudozufälligen Würfelzahlen beweisen kann, dass diese nicht zufällig sind. Zumindest nicht mit den Mitteln, die einem Programmieranfänger zur Verfügung stehen.

Vermutlich sollte der Fragesteller nicht 6 Millionen Werte in einem Array speichern, sondern in einem Array der Länge 6 die Häufigkeiten der Würfelwerte von 1 - 6 zählen. Und diese Häufigkeiten liegen sehr nahe dem Erwartungswert von 1 Mio pro Wert.

Tatsächlich falsch ist, dass man zwischen zwei Aufrufen der random() Funktion warten sollte, damit die Zahlen "zufälliger" werden oder dass parallel laufende Voränge im Computer die Zufälligkeit beeinflussen.

0
@Schachpapa

zum 1. Punkt.

Mit den Mitteln eines Programmieranfägern sicher nicht, es sind in der Statistik aber Algorithmen dafür verfügbar, sogar auf Taschenrechner.

zum 2. Punkt

Das sehe ich auch so.

zum Punkt 3.

Das bezieht sich sich auf die von mir beschriebene Methode, den Timer als Quelle heranzuziehen, wenn keine Randomfunktion verfügbar ist und ein Algorithmus verwendet wird. Falls verfügbar, kommt es darauf an, wie diese konzipiert ist. Die Idee, bei Wiederholungen auf vorherige Werte aufzubauen ist mir neu. Ich finde sie gut und werde bei Bedarf darauf zurückgreifen. Mein Entwicklungssystem ist schon älter und hat keine Randomfunktion. Danke für den Hinweis.

0
@wotan38

Wie macht man das mit den Mitteln eines Taschenrechners? Die 6 Millionen Werte eintippen ist ja schlecht möglich.

Den in Java benutzten "linearen Kongruenzgenerator" habe ich oben schon aufgeschrieben. Etwas detaillierter kann man es in der Doku nachlesen:
https://docs.oracle.com/javase/10/docs/api/java/lang/Math.html#random()

https://docs.oracle.com/javase/10/docs/api/java/util/Random.html

Der müsste relativ einfach nachzustricken sein. Womit entwickelst du?

0

Also, da in der Aufgabenstellung  steht, dass du die Ergebnisse in einem Array speichern sollst kannst du zunächst davon ausgehen, dass du ein geeignetes Array deklarieren musst. Z.B.

byte[] results = new byte[6000000];

Eine geeignete Schleife zum Befüllen des Arrays hast du bereits. Auf ein Element im Array kannst du mit results[index] zugreifen. Wenn du etwas für alle Elemente in einem beliebigen Array arr machen möchtest sieht es in der Regel so aus.

for(int i = 0; i < arr.length; i++) {

      //Mache etwas mit arr[i]

}

Wie du eine Zufallszahl auslost weißt du auch. Von daher hast du eigentlich alles nötige beisammen.

public static void main(String[] args){
       int array[] = new int[6000000]; //Erzeugt ein        //Array vom Typ int mit 6000000 Plätzen              for (int i=0; i<6000000; i++){
           array[i] = (int)((Math.random()*6)+1); 
           //Setzt an die Stelle i im Array eine                //  zufällige Zahl zwischen 1 und 6             }
}

weißt du auch zufällig wie ich jetzt die Häufigkeiten raus bekomme für 1 bis 6 ? 

0
@halbleeresgals

Klar. Einfach für jeden Wert eine Zählvariable anlegen und über das Array mit der for-Schleife iterieren mit einer switch-case-Anweisung prüfen, welche Zahl im Array gespeichert ist und die entsprechende Zählvariable um 1 erhöhen.

0
@PeterWolf42
wenn ich das so eingebe 
for (int i=0; i<=6000000; i++){                        array1[i]=(int)((Math.random()*6)+1);

dann kommt in der console "Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6000000at Wuerfel.main(Wuerfel.java:19)"

0
@halbleeresgals

Ja, weil die Speicherstellen im Array vom der Position 0 gezählt werden, d.h. ein Array der Länge 3 hat die Positionen 0,1,2. Deswegen zählt in meinem Code i ja auch nur solange hoch, solange es < (kleiner) als 6000000 ist.

0
@PeterWolf42

Also irgendwie seh ich jetzt hier nicht mehr durch wenn ich das ausführe

for (int i=0; i< 6000000; i++){           
 array1[i]=(int)((Math.random()*6)+1);            System.out.println(array1);

kommt folgendes 6000000 raus "[I@6d06d69c" ich denke da kommen random zahlen zwischen 1 und 6 hin

0
@halbleeresgals

Weil du mit 

System.out.println(array1);

versuchst, das Ganze Array an sich auszugeben. Um einen einzelnen Wert auszugeben, musst du z.B. 

System.out.println(array1[0]);

nutzen. 

0
@PeterWolf42

Oh stimmt den Fehler mach ich immer ;D

Und jetzt noch eine Frage zu den Switch anweisung mit der Zählervariablen wie meinst du das ? 

0
@halbleeresgals

Naja. Um die Häufigkeit zu ermitteln, musst du ja für jeden Wert array1[i] Prüfen, ob es eine 1, oder eine 2 usw. ist. Du könntest also 6 if-Anweisungen machen. Mit einer switch - case Anweisung lässt sich das jedoch mit einem Befehlt Testen.

Sei z.B. int zahl = 0;
switch( zahl){
  case 0: // tu was, wenn Zahl == 0; break;
  case 1: // tu was, wenn Zahl == 1; break;
}

So kann man für verschiedene Werte einer Variable verschiedene Aktionen machen. In deinem Fall würde man eine die entsprechende Zählvariable um eins erhöhen. Wichtig ist das break ; nicht zu vergessen, da sonst alle nachfolgenden Befehle in den switch-Block auch ausgeführt werden.

0
@PeterWolf42

ok egal was ich versuche ich habe wirklich null ahnung wie ich das umsetzen soll

0
@halbleeresgals

besser ohne switch; danach hat man in hi[n] die Anhahl per n:

int hi = new int[6]; // häufigkeiten

for (int i=0; i<6000000; i++) {
    int wert = array[i];

    hi[wert - 1]++;
}

for (int n=1; n<=6; n++) {
System.out.println("häufigkeit von "+n
+" ist "
+hi[n-1]);
}
0

Einfach jede Zahl getrennt für sich zählen. Der Mittelwert für eine Zahl beträgt eine Million. Jetzt kannst in % ausrechnen, wie groß die Abweichung vom Mittelwert im einzelnen ist. Damit hast aber noch keine Aussage über die Verteilung. Denn es könnte ja sein, dass zuerst alle Einsen hintereinander kommen, dann alle Zweier und so fort. Dann könntest auch eine gleichmäßige Häufigkeit feststellen, obwohl es dann keine Zufallszahlen wären. Dazu müsstest noch die einzelnen Abstände zählen und den Mittelwert berechnen und mit dem Sollwert vergleichen.