Avatar billede chriz7913 Nybegynder
27. august 2008 - 10:13 Der er 13 kommentarer og
2 løsninger

Forskellige random tal

Faldt lige over spørgsmålet:
Hvis jeg gerne vil have udskrevet 5 forskellige random tal på skærmen, hvordan gør jeg så?
Man kan jo altid sige:
$rand1 = rand(1,10);
$rand2 = rand(1,10);
$rand3 = rand(1,10);
$rand4 = rand(1,10);
while($rand1 == $rand2){
$rand1 = rand(1,10);}
while($rand1 == $rand3){
$rand1 = rand(1,10);}
osv, men det kommer bare til at fylde meget kodemæssig, så nogen der kender en anden løsning, evt en funktion?
- Chris
Avatar billede bitmatic Nybegynder
27. august 2008 - 10:53 #1
1. Du laver et array med tallene fra 1-10.
2. Så "blander" du array'et med funktionen shuffle.
3. Så udskriver du de første 5 tal i array'et.

se: http://dk2.php.net/shuffle
Avatar billede jakobdo Ekspert
27. august 2008 - 10:55 #2
<?php
//http://www.eksperten.dk/spm/843184

$tal = range(1,10);
$antal_tal = 5;
for($i = 0; $i < $antal_tal; $i++){
    shuffle($tal);
  echo $tal[0] . '<br />';
  unset($tal[0]);
}

?>
Avatar billede jakobdo Ekspert
27. august 2008 - 10:56 #3
Og en smarterer løsning:

<?php
//http://www.eksperten.dk/spm/843184

$tal = range(1,10);
$antal_tal = 5;
shuffle($tal);
$random_tal = array_slice($tal,$antal_tal);
echo implode('<br />', $random_tal);

?>
Avatar billede bitmatic Nybegynder
27. august 2008 - 11:00 #4
$numbers = range(1,10);
shuffle($numbers);
for($i = 0; $i < 5; $i++)
{
  echo $numbers[$i];
}
Avatar billede jakobdo Ekspert
27. august 2008 - 11:12 #5
Lille rettelse:

<?php
//http://www.eksperten.dk/spm/843184

$tal = range(1,10);
$antal_tal = 5;
shuffle($tal);
$random_tal = array_slice($tal,0,$antal_tal);
echo implode('<br />', $random_tal);

?>
Avatar billede jakobdo Ekspert
27. august 2008 - 11:14 #6
Og som funktion:

<?php
//http://www.eksperten.dk/spm/843184

function uniqueRandomNumbers($count=5,$max=10,$min=1){
    $numbers = range($min,$max);
    shuffle($numbers);
    return array_slice($numbers,0,$count);
}

echo implode('<br />', uniqueRandomNumbers(10,100,1));

?>
Avatar billede chriz7913 Nybegynder
30. august 2008 - 20:04 #7
Tak for de mange muligheder, i kan dele pointene (:
Smid et svar begge
Avatar billede jakobdo Ekspert
30. august 2008 - 21:33 #8
Svar!
Avatar billede bitmatic Nybegynder
30. august 2008 - 22:32 #9
:)
Avatar billede arne_v Ekspert
31. august 2008 - 22:45 #10
Det er værd at bemærke at der er 2 principielle metoder:
* den beskrevne - generer $min..$max, shuffle og pick $count
* pick $count rand($min, $max) og repick hvis allerede picked

Den optimale metode afhænger af værdierne for $count, $max og $min. Generelt vil
høj $count/($max-$min) favorisere shuffle mens lav vil favorisere test.

For 5/10 er der naturligvis ikke nogen målbar forskel.
Avatar billede jakobdo Ekspert
01. september 2008 - 14:10 #11
arne_v: Gider du ikke give en lidt længere forklaring på, hvad forskellen er ? Og hvorfor der er en forskel ? Og hvis ikke det er at presse citronen for meget, et kode eksempel som beviser din påstand. :o)
Avatar billede arne_v Ekspert
01. september 2008 - 15:30 #12
Det er en forholdsvis dyr operation at create et range of shuffle dem når range ($max-$min+1)
bliver stort mens det ikke gør den store forskel om hvorvidt man skal tage et lille
eller stort antal ($count) ud af resultatet.

Modsat er generering af et random tal helt uafhængigt af range ($max-$min+1) mens
til gengæld så koster det ved et simpelt test rigtigt dyrt for hver eneste pick
at skulle løbe de allerede udtrukne numre igennem. Det kan kan man lave smartere.
Men så render man ind i problemet at når $count nærmer sig ($max-$min+1) skal man
trække rigtigt mange tilfældige numre for at finde et der ikke allerede er udtrukket.
Avatar billede arne_v Ekspert
01. september 2008 - 15:30 #13
<?php
function unique_ran_shuffle($count, $min, $max) {
    $all = range($min, $max);
    shuffle($all);
    return array_slice($all, 0, $count);
}

function unique_ran_test($count, $min, $max) {
    $num = array();
    for($i = 0; $i < $count; $i++) {
        do {
            $val = rand($min, $max);
        } while(array_search($val, $num));
        $num[] = $val;
    }
    return $num;
}

function unique_ran_testsmart($count, $min, $max) {
    $num = array();
    $numchk = array();
    for($i = 0; $i < $count; $i++) {
        do {
            $val = rand($min, $max);
        } while(array_key_exists($val, $numchk));
        $numchk[$val] = true;
        $num[] = $val;
    }
    return $num;
}

/*
echo "Shuffle 1 out of 10:<br>\r\n";
echo implode("<br>\r\n", unique_ran_shuffle(1, 1, 10));
echo "<hr>\r\n";
echo "Shuffle 10 out of 10:<br>\r\n";
echo implode("<br>\r\n", unique_ran_shuffle(10, 1, 10));
echo "<hr>\r\n";
echo "Test 1 out of 10:<br>\r\n";
echo implode("<br>\r\n", unique_ran_test(1, 1, 10));
echo "<hr>\r\n";
echo "Test 10 out of 10:<br>\r\n";
echo implode("<br>\r\n", unique_ran_test(10, 1, 10));
echo "<hr>\r\n";
echo "Test (smart) 1 out of 10:<br>\r\n";
echo implode("<br>\r\n", unique_ran_testsmart(1, 1, 10));
echo "<hr>\r\n";
echo "Test (smart) 10 out of 10:<br>\r\n";
echo implode("<br>\r\n", unique_ran_testsmart(10, 1, 10));
*/

$t1 = microtime(true);
unique_ran_shuffle(10, 1, 100000);
$t2 = microtime(true);
echo "Shuffle 10 out of 100000: " . sprintf("%.3f", $t2 - $t1) . "<br>\r\n";
echo "<hr>\r\n";
$t1 = microtime(true);
unique_ran_shuffle(10000, 1, 100000);
$t2 = microtime(true);
echo "Shuffle 10000 out of 100000: " . sprintf("%.3f", $t2 - $t1) . "<br>\r\n";
echo "<hr>\r\n";
$t1 = microtime(true);
unique_ran_shuffle(5000, 1, 5000);
$t2 = microtime(true);
echo "Shuffle 5000 out of 5000: " . sprintf("%.3f", $t2 - $t1) . "<br>\r\n";
echo "<hr>\r\n";
$t1 = microtime(true);
unique_ran_test(10, 1, 100000);
$t2 = microtime(true);
echo "Test 10 out of 100000: " . sprintf("%.3f", $t2 - $t1) . "<br>\r\n";
echo "<hr>\r\n";
$t1 = microtime(true);
unique_ran_test(10000, 1, 100000);
$t2 = microtime(true);
echo "Test 10000 out of 100000: " . sprintf("%.3f", $t2 - $t1) . "<br>\r\n";
echo "<hr>\r\n";
$t1 = microtime(true);
unique_ran_test(5000, 1, 5000);
$t2 = microtime(true);
echo "Test 5000 out of 5000: " . sprintf("%.3f", $t2 - $t1) . "<br>\r\n";
echo "<hr>\r\n";
$t1 = microtime(true);
unique_ran_testsmart(10, 1, 100000);
$t2 = microtime(true);
echo "Test (smart) 10 out of 100000: " . sprintf("%.3f", $t2 - $t1) . "<br>\r\n";
echo "<hr>\r\n";
$t1 = microtime(true);
unique_ran_testsmart(10000, 1, 100000);
$t2 = microtime(true);
echo "Test (smart) 10000 out of 100000: " . sprintf("%.3f", $t2 - $t1) . "<br>\r\n";
echo "<hr>\r\n";
$t1 = microtime(true);
unique_ran_testsmart(5000, 1, 5000);
$t2 = microtime(true);
echo "Test (smart) 5000 out of 5000: " . sprintf("%.3f", $t2 - $t1) . "<br>\r\n";
?>
Avatar billede jakobdo Ekspert
01. september 2008 - 16:01 #14
Takker arne_v, kan godt se der er en forskel, omend den ikke er super stor. :o)
Avatar billede jakobdo Ekspert
02. september 2008 - 08:04 #15
Takker for point.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester