2016-09-24 6 views
0

Ich habe ein JavaScript-Buch gekauft und arbeite mich durch. Ich habe einen Teil des Buches erreicht, der keinen Sinn ergibt. Ich hoffe, dass ihr Jungs und Mädels klären könnt, wie es das Buch nicht tut.Ein Array mit zufälligen Ganzzahlwerten füllen

Bitte beachten Sie den folgenden Code, der 6 Zufallszahlen erzeugt und sie zu einem Div mit id=panel rendert.

function init(){ 
var panel = document.getElementById('panel'); 
var i, rand, temp, str, num = []; 

for (i = 1; i < 50; i ++){ 
    num[i] = i; 
} 

for (i = 1; i < 50; i ++){ 
    rand = Math.ceil(Math.random()*49); 
    temp = num[i]; 
    num[i] = num[rand]; 
    num[rand] = temp; 
} 

str = 'Your six lucky numbers:<br>'; 
for (i = 1; i < 7; i ++){ 
    str += num[i]; 
    if (i !==6){str += ' - ';} 
} 
panel.innerHTML += str; 

} 
document.addEventListener('DOMContentLoaded', init, false); 

Das Buch sagt, daß die zweite Schleife (das initilizes die Zufallsvariable) einen Sortieralgorithmus enthält, die keine zwei Elemente enthalten, die gleiche Anzahl gewährleistet.

Ich bin mir nicht sicher, wie das möglich ist, ich sehe keinen Code darin, der rand stoppt, der eine doppelte Zahl enthält und infolgedessen diesen Wert in num gespeichert hat. Das Buch liefert nicht wirklich eine Erklärung für das, was vor sich geht.

Könnte mir bitte jemand sagen, wie, wenn überhaupt, Schleife zwei verhindert, dass "num" die gleiche Nummer enthält?

Vielen Dank alle

P.S. Entschuldigung, wenn diese Frage nicht den Stack Overflow-Richtlinien entspricht. Ich komme nicht oft hierher, nur wenn ich wirklich feststecke und anderswo keine Antwort finde.

Antwort

1

Die for-Schleife wird zunächst nur ein Array von 49 Elementen zu schaffen, wobei jedes Array-Element an seinen Index gleich zu sein:

num[1] = 1 
num[2] = 2 
etc. 

die zweiten für-Schleife, die zufällig mischt Dies steht im Mittelpunkt der Frage Geordnetes Array.

als Beispiel:

1. Iteration der for-Schleife, sagen wir den Wert von rand , die Logik in der Schleife wird dann Swops den Wert in num [23] mit dem Wert in num [1 ], so dass Sie am Ende mit:

num[1] being equal to 23 (because num[23] was equal to 23 as per above) 
num[23] being equal to 1 

zweite Iteration der for-Schleife, rand von sagen, dass der Wert bekommt, Swops die Logik in der Schleife dann den Wert in num [18] mit dem Wert in num [2], so dass Sie enden mit:

num[2] being equal to 18 (because num[18] was equal to 18 as per above) 
num[18] being equal to 2 

Dies wird 49 mal passieren.

Dies ist auch der Grund für Math.random() mit 49 multipliziert wird, gibt es nur 49 Array-Elemente mit Werten.

TL; DR; Geordnetes Array wird gemischt.

+0

Vielen Dank für die Erklärung. Ich musste es genau so durchgehen, wie du es gerade verstanden hast, aber ich war mir nicht sicher, ob ich recht hatte. Was ist zu verhindern, dass 'Math.random()' die gleiche Nummer zweimal erzeugt? – Pete

+0

Es gibt nicht, aber lassen Sie uns sagen, zufällige erzeugt 32 sowohl auf der dritten als auch der 15. Iteration. Es wird den 32. und den 3. Wert tauschen, also num [32] = 3 und num [3] = 32 nach dem Wechsel. Jetzt, in der 15. Iteration, wird num [15] mit num [32] ausgetauscht, aber num [32] enthält nun 3, also num [15] = 3 und num [32] = 15 nach dem swop. Es spielt also keine Rolle, ob es mehr als einmal einen zufälligen Wert erzeugt. –

+0

vielen Dank!Ich konnte nicht für das Leben von mir das herausfinden. Ich verstand, was das Programm machte, nur nicht die Wirkung, die es verursachen würde. Nochmals vielen Dank für die Panne, genau das, was ich brauchte. +1: D – Pete

1

Diese Schleife erzeugt ein sortiertes Array 1-49:

for (i = 1; i < 50; i ++){ 
    num[i] = i; 
} 

Diese Schleife Nachbestellungen jede Position (i) der Anordnung mit einer anderen zufälligen Positionrand durch die beiden Swapping. Es werden keine neuen Zufallszahlen generiert, sondern nur zufällig bestehende Nummern neu geordnet. rand ist ein Index, in diesem Fall kein Wert. Keine zwei Zahlen können gleich sein, weil die erste Schleife nur eine Instanz jeder Zahl in das Array platziert hat.

for (i = 1; i < 50; i ++){ 
    rand = Math.ceil(Math.random()*49); 
    temp = num[i]; 
    num[i] = num[rand]; 
    num[rand] = temp; 
} 
+0

Vielen Dank für Ihre Hilfe. Mein Verständnis stimmte von dem, was alle mir gesagt haben. Worüber ich noch verwirrt bin, ist 'Math.ceil (Math.random() * 49);' erzeugt eine Zufallszahl zwischen 1 und 49. Obwohl es nur 49 Runden durchläuft. Kann "Math.random" beispielsweise nicht zweimal 14 mal generieren? – Pete

+1

Es ist fast sicher, dass es dieselbe Nummer zweimal erzeugt. Also wird eine Nummer mit 14 getauscht, dann wird diese Nummer wieder mit einer anderen getauscht. Es ist sogar möglich, dass die Nummer an ihren ursprünglichen Platz zurückkehrt. Aber hey, das ist Zufälligkeit! Auch wenn ich es verwendet habe ich die Füllung, dass dieser Algorithmus voreingenommen ist. Ich denke, es ist besser, ein anderes Array zu füllen, indem man in der ersten Zufallszahlen auswählt. – bokan

1

Diese Schleifen füllt und Array mit 50 Zahlen von 1 bis 50.

Dann mischt sie gerade. Die rand-Variable wird verwendet, um einen zufälligen Index in dem Array zu zeigen.

2

Sie können sich die zwei Schleifen wie folgt vorstellen: Die erste erzeugt ein Deck von 49 "Karten" (hier durch die Zahlen 1 bis 49 dargestellt). Die zweite Schleife mischt dann diese "Karten", indem sie jede Karte wiederholt mit einer zufälligen auswechselt.

Hinweis gibt es zwei Probleme mit dem Code. Erstens ist es nicht notwendig, das gesamte Array zu mischen, wenn nur 6 Elemente ausgewählt werden. So könnte die zweite Schleife bei 6 anstelle von 50 enden.

Aber es gibt ein ernsteres Problem mit dem Code, es verwendet den falschen Algorithmus, um Arrayelemente zu mischen. Dieser Algorithmus erzeugt nicht alle möglichen Permutationen der Elemente mit der gleichen Wahrscheinlichkeit.

Hier ist die richtige Version:

for (i = 1; i < 50; i ++){ 
    rand = i + Math.floor(Math.random()*(50 - i)); 
    temp = num[i]; 
    num[i] = num[rand]; 
    num[rand] = temp; 
} 

Die Idee ist, das aktuelle Element in der Schleife zu tauschen, nur mit einem nachfolgenden Element (einschließlich sich selbst). Beachten Sie, dass wenn Sie die obige Schleife so schreiben, dass sie rückwärts läuft (d. H. Von 49 auf 1), macht sie es etwas einfacher und ich bevorzuge diesen Ansatz.

+0

Ich würde nicht sagen, dass das zweite Problem so ernst ist - zumindest nicht in diesem Szenario. Es sind "Glückszahlen", keine Raketenwissenschaft. – Xufox

+0

Nun, der richtige Algorithmus ist nicht wesentlich komplizierter und es gibt keinen Grund, Leuten beizubringen, den falschen Algorithmus zu verwenden. – redneb

+1

für i gleich 1, das würde möglicherweise 50 als Index zurückgeben, der nicht existiert (wenn Math.random() 0.9999 zurückgibt, dann 0.9999 * (51-1) + 1 ist gleich 49.99, von denen die Obergrenze 50 ist) aber stimme zu, es ist besser, einige dieser Regeln über zufällige früh zu lernen –

Verwandte Themen