phpbar.de logo

Mailinglisten-Archive

[php] randomize?

[php] randomize?

Werner Stuerenburg ws_(at)_art-quarter.com
Thu, 07 Oct 1999 08:54:44 +0200


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