Mailinglisten-Archive |
Abweichend vom sonstigen Schema des Frage/Antwort-Spiels gebe ich heute eine Antwort und außerdem den Zusammenhang. Ich denke, daß der eine oder andere (z. B. ich, wenn ich nicht zufällig der Autor wäre) davon profitieren kann. Ist das eine gute Idee? Vielleicht kann man sowas direkt ins php-Center übernehmen; ich merke, daß es leichter ist, einen Beitrag für die Liste zu schreiben als fürs Center (nicht wahr, Björn?). Martin Ramsch am 22 Sep 1999: > Stephan Noller schrieb am Dienstag, den 21. September 1999: > > ich moechte eine Reihe von 20 Zahlen per Zufall sortieren. (Also 20x > > ziehen ohne zuruecklegen). > $z = array(1,2,3,5,8,13,21); > > Falls Du eine PHP-Version hast, die noch nicht die Funktion shuffle() > bietet, könntest Du so vorgehen: > > $n = count($z); > $i = 0; > while($i<$n) { > $j = rand(0,$n-1); > while ($flag[$j]) { $j = ($j+1) % $n; } > printf("%d. Element: %d<br>\n", $i+1, $z[$j] ); > $i++; > } Ich erinnerte mich, aber ich verstehe es nicht. Und siehe da: es funktioniert auch nicht! 1. Element: 1 2. Element: 5 <=== 3. Element: 2 4. Element: 13 5. Element: 8 6. Element: 5 <=== 7. Element: 3 Wegen Version 3.0.7 steht mir die Funktion shuffle() auf dem Host auch nicht zur Verfügung. Ich habe mir daher gebastelt: function shuffleNumbers($total, $num){ for ($i = 0; $i < $total; $i++) { $ar[] = $i; } if ($total < $num) { $num = $total; } for ($j = 0; $j < $num; $j++) { $rndNo = randNumber($total -$j)-1; $res[] = $ar[$rndNo]; $ar[$rndNo] = $ar[$total-$j-1];//neuen Wert zuordnen } return $res; } Diese Funktion zieht $num Zufallszahlen aus $total fortlaufenden Zahlen (ist direkt dem richtigen Leben nachgebaut). Das Ergebnis kann man dann benutzen, um aus irgendwelchen Arrays zufällige Werte herauszuziehen (siehe aber dazu auch Kommentar zum Schluß). Ich benutze die Funktion randNumber, die Fragen aufwirft: function randNumber($end, $start = 1){ if ($end == $start) { return $end; } mt_srand((double)microtime()*1000000); $res = mt_rand($start, $end); while ($res == ""){ $res = mt_rand($start, $end); } if ($res > $end) { $res %= ($end - $start + 1); $res += $start; } return $res; } Zunächst habe ich mit rand() gearbeitet, dabei aber Unerwartetes erlebt. while ($res == ""){ $res = mt_rand($start, $end); } habe ich wohl eingebaut, weil rand() manchmal keine Werte lieferte (!), und ich im Falle von mt_rand() ebenfalls sichergehen wollte. if ($res > $end) { $res %= ($end - $start + 1); $res += $start; } mußte ich einbauen, weil mt_rand() im Gegensatz zur Definition nicht die gewünschten Werte lieferte. ==================== Zitat aus dem Manual ==================== mt_rand mt_rand -- generate a better random value Description int mt_rand([int min], [int max]); Many random number generators of older libcs have dubious or unknown characteristics and are slow. By default, PHP uses the libc random number generator with the rand() function. mt_rand() function is a drop-in replacement for this. [...] If called without the optional min,max arguments mt_rand() returns a pseudo-random value between 0 and RAND_MAX. If you want a random number between 5 and 15 (inclusive), for example, use mt_rand(5,15). Remember to seed the random number generator before use with mt_srand(). ============== Probe aufs Exempel: mt_srand((double)microtime()*1000000); $res = mt_rand(5,15); liefert beim ersten Versuch $res = 19101 (ich fahre lokal Version 3.0.9) Die Zufallswerte mit rand() waren mir bei näherer Betrachtung deutlich nicht zufällig genug - daher scheint mir diese Funktion eigentlich unbrauchbar. Anwendung: Ich entwickle gerade eine Seite für einen Pkw-Anhängervertrieb. Dazu habe ich zunächst die erste Ebene entworfen; auf vielen Seiten habe ich unten drei oder mehr Fotos plaziert. Diese Fotos werden automatisch passend zum Thema zufällig ausgewählt und bei jedem Laden der Seite neu gemischt. Um überhaupt ein vernünftiges Design verwirklichen zu können, habe ich die Thumbnails alle auf 200 Pixel Breite genormt, sodaß auf allen Bildschirmen gut drei nebeneinander passen. Jedes Thumbnail wird in eine eigene Tabelle gepackt, die eine abweichende Hintergrundfarbe hat, was dann einen Rahmen ergibt. Die Auswahl der Bilder und die Präsentation hängt lediglich vom Verzeichnis und einem Steuerelement ab. Die ganze Geschichte funktioniert also sozusagen vollautomatisch. Beispiel: der Menüpunkt lautet "Kipper", angewählt wird $HTTP_HOST/kipper/index.html, index.html kann also den String "kipper" über die Funktion getDirName() selbst finden. Der Rest ergibt sich von selbst. Die Inhalte zum Thema liegen in $HTTP_HOST/inc/getDirName()/, die Bilder dazu in $HTTP_HOST/img/getDirName()/ Über den Schalter $all wähle ich an, ob ich alle verfügbaren Bilder miteinbeziehen will oder nur die zum Thema. Der Schalter $cnt = "max" gibt mir die maximale Anzahl der zum Thema verfügbaren Bilder, ansonsten gebe ich damit die absolute Anzahl der Bilder an, falls ich von der Voreinstellung abweichen will. Das Template tableRandomImages.php3 macht den Rest, wertet also die Schalter aus, produziert die Liste der Dateinamen für die Bilder und stellt das ganze in eine entsprechende Tabelle ein, macht sich also selbst die erforderliche Anzahl von Spalten und Reihen: <?php if ($cnt == "") { $cnt = 3; //Voreinstellung } if (!$all) { $filename = getDirName(); //Directory bestimmen $arThumbs = getRandomThumbsDir($filename, $cnt); //Dateinamen auslesen, $cnt beliebige auswählen } else { $arThumbs = getRandomThumbs($cnt); //Dito, alle Verzeichnisse einbeziehen } $cnt_ar = count($arThumbs); //Anzahl der Bilder $cnt_rows = ceil($cnt_ar / 3); //Anzahl der Zeilen, drei Bilder pro Zeile /* Nun springe ich immerzu raus aus php und wieder rein. Grundsätzlich ergibt sich dadurch ein kleiner Zeitvorteil, der jedoch in der Praxis erst bei riesigen Iterationen bemerkbar wird. Der HTML-Code ist sozusagen roh; ob dieser Art der Schreibweise für den konstruierten Nur-Designer leichter lesbar ist als eine Echo-Variante, kann ich nicht entscheiden. */ ?> <CENTER> <TABLE BORDER='0' CELLSPACING='0' CELLPADDING='20' ALIGN='Center'> <?php for ($j = 0; $j < $cnt_rows; $j++) { //Iteration für die Zeilen ?> <TR> <?php $num_per_row = $cnt_ar / $cnt_rows; //Berechnung Anzahl Bilder pro Zeile $start = $j * $num_per_row; $end = $num_per_row * ($j+1); //Werte für jede einzelne Zeilen for ($i = $start; $i < $end; $i++) { //Iteration pro Zeile ?> <TD> <CENTER><A NAME='<?php echo $arThumbs[$i]; ?>'><!-- --></A> <TABLE BORDER='0' CELLSPACING='0' CELLPADDING='4' > <TR> <TD bgcolor='#777891'> <IMG SRC='http://siemsgluess-anhaenger.de/img/<?php echo $arThumbs[$i]; ?>' width='200'></TD> </TR> </TABLE> </CENTER> </TD> <?php } ?> </TR> <?php } ?> </TABLE> </CENTER> Soweit der Anfang von http://siemsgluess-anhaenger.de/ Die verfügbaren Bilder sind teilweise noch von schlechter Qualität, das ändert sich aber in den nächsten Tagen. Eventuell muß man je nach Beschaffenheit des Arrays noch eine Sonderbehandlung einbauen. So habe ich zum Beispiel mehrere Stunden gebraucht, um herauszufinden, warum trotzdem manchmal dasselbe Bild mehrfach gezeigt wurde. Das lag daran, daß ich dasselbe Bild in verschiedenen Unterverzeichnisse liegen hatte, zum Beispiel sowohl in der entsprechenden Rubrik (Kipper) als auch im Verzeichnis des Herstellers (Westfalia). Die Auswahl war zwar zufällig, die Dateinamen waren auch verschieden, es war aber dasselbe Bild, also sozusagen dieselbe Karte zweimal im Spiel. Die Zeit habe ich damit verbracht, an der falschen Stelle zu suchen, wie das meistens der Fall ist, wenn man den Fehler nicht gleich findet. -- Mit freundlichem Gruss Werner Stuerenburg ____________________________________________________________ ISIS Verlag - Uhlandstr. 8 - D-32120 Hiddenhausen - Germany Tel. 0(049)5224-9974-07, Fax-09, <mailto:ws_(at)_art-quarter.com> < http://pferdezeitung.com/ > - < http://art-quarter.com/ >
php::bar PHP Wiki - Listenarchive