Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1
    Utente di HTML.it
    Registrato dal
    Jul 2014
    Messaggi
    62

    generare numeri casuali senza ripetizione

    Ciao a tutti!!
    Sto facendo un programma che in futuro sarà chiamato tantissime volte. Questo programma estrae a sorte 7 numeri compresi tra 0 e 300 se non di più. Adesso, quale la possibilità che questo programma mi darà 2 numeri uguali?
    Cercavo un modo per eliminare da un array eventuali numeri identici creati e rimpiazzarli con altri numeri diversi, il tutto sempre per avere 7 numeri diversi.
    Voi che pensate? avendo cosi tanti numeri a disposizione, la probabilità di avere 2 numeri identici sia quasi nulla o comunque devo inserire nel programma un controllo?


    Grazie in anticipo

  2. #2
    Utente di HTML.it L'avatar di badaze
    Registrato dal
    Jun 2002
    residenza
    Lyon
    Messaggi
    5,372
    Più lo chiamerai più avrai chance di avere doppioni. Quindi controlla.
    Ridatemi i miei 1000 posts persi !!!!
    Non serve a nulla ottimizzare qualcosa che non funziona.
    Cerco il manuale dell'Olivetti LOGOS 80B - www.emmella.fr

  3. #3
    La probabilità che capitino due numeri uguali non è bassa, ma neanche alta, ma è comunque necessario inserire un controllo. Io pensavo a qualcosa del genere:
    Codice PHP:
    $arrayNumeri = array();//creo l'array dei numeri
       
    for($x 0$x 7$x++){//inizio un ciclo da ripetere 7 volte
       
    $controllo true;//creo una variabile di controllo
       
    while($controllo){//ripeto l'azione fino a qaundo controllo non diventa false
          
    $numero rand(0,300);
          if(!
    in_array($numero$arrayNumeri)){//controllo che il numero non sia già presente
             
    $arrayNumeri[] = $numero;//aggiungo il numero all'array
             
    $controllo false;//interrompo il ciclo
          
    }//fine if
       
    }//fine ciclo while
    }//fine ciclo for 
    Spero di essere stato utili, fammi sapere
    Pino

  4. #4
    Utente di HTML.it L'avatar di badaze
    Registrato dal
    Jun 2002
    residenza
    Lyon
    Messaggi
    5,372
    Oppure.
    Codice PHP:
    <?php    
    $i 
    0;    
    $array = array();    
    while (
    $i<=7) {        
      
    $Casrand(1,300);        
      if (! 
    in_array($Cas,$array)) {            
        
    $array[]=$Cas;            
        
    $i++;        
      }
    }    
    print_r($array);?>
    Ridatemi i miei 1000 posts persi !!!!
    Non serve a nulla ottimizzare qualcosa che non funziona.
    Cerco il manuale dell'Olivetti LOGOS 80B - www.emmella.fr

  5. #5
    Utente di HTML.it L'avatar di joker06
    Registrato dal
    Dec 2006
    Messaggi
    782
    badaze, fai un giro di troppo nel ciclo.
    codice:
    //fai partire i da 1
    $i = 1;
    
    // oppure il controllo del ciclo deve esser minore di 7
    while ($i<7) // questo se continui ad avere $i = 0;

  6. #6
    Utente di HTML.it L'avatar di Grino
    Registrato dal
    Oct 2004
    Messaggi
    739
    Brutta soluzione... Chiamare tante volte in_array non è carino!

    ti consiglio per avere una cosa veloce, visto che lo chiami tante volte e al crescere delle estrazioni aumentano le probabilità di estrarre un numero già estratto, di creare un array contenente i numeri. Quindi estrai da questo array, con numeri in ordine casuale, il quantitativo di elementi che ti occorre.

    http://php.net/manual/en/function.shuffle.php

    Nel manuale hai l'esempio per creare il tuo arrai di tutti i numeri in ordine casuale. Con array_pop li tiri fuori e avrai delle estrazioni casuali senze ripetizione velocissime.

    Siamo sempre troppo gelosi delle nostre grandi piccole opere! - Grino inedito.
    Lavori e Lavoretti

  7. #7
    Utente di HTML.it L'avatar di clasku
    Registrato dal
    Aug 2006
    Messaggi
    3,197
    sai che ho fatto delle prove e array_pop risulta più veloce solo sotto la soglia di 40 elementi da estrarre?
    dopo è più veloce la soluzione in_array

    metto il codice che ho usato per il test
    Codice PHP:
    <?php


    $s 
    1// valore di partenza per random
    $t 300// valore di fine per random
    $n 7// numero di elementi da estrarre


    $p 0// contatore ripetizioni per test
    $p_max 1000// numero di ripetizioni per test


    $faster_2 0// variabile contatore per contare quando array_pop è più veloce


    while($p $p_max) {
        
    // inizio con in_array()
        
    $start1 microtime();
        
    $range = array();
        for(
    $a 0$a <= $n$a++) {
            
    $num rand($s$t);
            if(!
    in_array($num$range)) {
                
    $range[] = $num;
            } 
        }
        
    $elapsed1 microtime() - $start1;
        
        
    // proseguo con array_pop()
        
    $start2 microtime();
        
    $range1 range($s$t);
        
    $range1_out = array();
        
    shuffle($range1);
        for(
    $a 0$a <= $n$a++) {
            
    $range1_out[] = array_pop($range1);
        }
        
    $elapsed2 microtime() - $start2;
        
        
    // delta di esecuzione dei due metodi
        
    $delta $elapsed1 $elapsed2;
        
        
    // se array_pop è più veloce, aggiungo al contatore
        
    if($delta 0) {
            
    $faster_2++; 
        }
        
    $p++;
    }


    echo 
    "array pop è più veloce nel " $faster_2 $p_max 100 "% dei casi\n";
    ?>

  8. #8
    Utente di HTML.it L'avatar di badaze
    Registrato dal
    Jun 2002
    residenza
    Lyon
    Messaggi
    5,372
    Quote Originariamente inviata da Grino Visualizza il messaggio
    Brutta soluzione... Chiamare tante volte in_array non è carino!
    Peggio ancora.
    Codice PHP:
    <?php
    $array 
    = array();
    while (
    count($array)!=7) {  
      
    $array[rand(0,300)]=1;
    }
    $array2 array_keys($array);
    print_r($array2);?>
    Ridatemi i miei 1000 posts persi !!!!
    Non serve a nulla ottimizzare qualcosa che non funziona.
    Cerco il manuale dell'Olivetti LOGOS 80B - www.emmella.fr

  9. #9
    Utente di HTML.it L'avatar di Grino
    Registrato dal
    Oct 2004
    Messaggi
    739
    clasku, ti sei dato un gran da fare! badaze... su grandi intervalli con poche estrazioni è sicuramente avvantaggiata dalla dea bendata.

    Ammettiamo che array_pop sia una funzione sciagurata che anzichè spostare il puntatore nel vettore avanti di uno restituendo l'elemento appena scartato e riducendo la dimensione del vettore effettui una copia integrale dell'array a meno di un elmento. Ciò nonostante è facilmente aggirabile l'uso di array_pop. Di contro sappiamo che in_array effettua una ricerca lineare, quindi l'algoritmo proposto all'inizio del 3d ha complessità esponeneziale.

    Quello che propongo ha complessità lineare. Certo potrai avere il caso fotunato in cui il tuo test potrà dirti che quello con complessità esponenziale si è comportato meglio, ma una complessità lineare è sicuramente meglio. Per cortesia evitiamo di criticare la classe .

    Codice PHP:
    <?php
    class GeneratoreNumeri{
        private 
    $elenco=array();
        private 
    $ultimo=0;
        private 
    $dim=0;
        
        public function 
    __construct($min,$max) {
            
    $this->rigenera($min$max);
        }
        
        public function 
    rigenera($min,$max){
            
    $temp=range($min,$max);
            
    shuffle($temp);
            
    $this->elenco=$temp;
            
    $this->dim count($this->elenco);
        }
        
        public function 
    rand(){        
            if(
    $this->dim>0){
                
    $this->dim--;
                return 
    $this->elenco[$this->ultimo++];
            }else
                throw new 
    Exception("Non ci sono più elementi da estrarre");        
        }
    }
    ?>
    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>Estrazioni casuali</title>
        </head>
        <body>
            <?php
                 $numEstrazioni 
    30;
                 
    $generatore = new GeneratoreNumeri(1100);
                 for(
    $i=0$i<$numEstrazioni$i++)
                    echo 
    $generatore->rand().'; ';
            
    ?>
        </body>
    </html>
    Ora divertiti pure a fare i test, ma non venirmi a raccontare che un algoritmo con complessità lineare è peggiore di uno con complessità esponenziale.

    Siamo sempre troppo gelosi delle nostre grandi piccole opere! - Grino inedito.
    Lavori e Lavoretti

  10. #10
    Utente di HTML.it L'avatar di clasku
    Registrato dal
    Aug 2006
    Messaggi
    3,197
    e mica stavo mettendo in discussione il fatto che la tua soluzione sia più prestante e lo so bene che una complessità esponenziale è peggiore di una lineare...
    ho voluto togliermi una curiosità in un noioso pomeriggio estivo di pioggia

    PS: ho altro per divertirmi invece che fare test

Tag per questa discussione

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.