Visualizzazione dei risultati da 1 a 9 su 9
  1. #1

    [C] generare numeri random

    Salve, come da titolo il mio problema è generare numeri random. La cosa non è però così semplice (almeno per me), poiché un programma principale crea dei figli (nei sistemi unix), tramite una fork(), e i figli hanno tutti lo stesso codice.

    codice:
    Esempio
    void child(int shm){
      srand(time(NULL));
      sleep(rand()%5);
    ...
    }
    
    int main(){
    ...
    for(i=0;i<5;i++)
      if(fork() == 0) child(shm);
    ...
    }
    In questo caso ogni figlio genera un numero random, ma questo è uguale per tutti i figli!
    Io vorrei che ogni figlio facesse una pausa diversa dall'altro.
    Spero di essere stato chiaro, grazie.

  2. #2
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326

    Re: [C] generare numeri random

    Con questo:

    Originariamente inviato da peppeocchi
    Io vorrei che ogni figlio facesse una pausa diversa dall'altro.
    intendi dire che i 5 processi figli che vengono generati devono aspettare ciascuno un tempo diverso da tutti gli altri o semplicemente che non devono attendere tutti lo stesso numero di secondi (come invece succede con quel codice) ? Lo chiedo perché quel rand()%5 mi fa pensare che vuoi ottenere il primo effetto, visto che con quella istruzione possono essere generati esattamente 5 valori interi random tra 0 e 4... insomma non può succedere che sia il primo che il quarto processo (ad esempio) attendando entrambi 3 secondi?

    Inoltre, a cosa serve la variabile shm?
    every day above ground is a good one

  3. #3
    Ok, rispondo con ordine, la variabile shm è un intero ritornato dalla chiamata shmget() per l'allocazione di memoria condivisa, per comunicare tra padre e processi figli.

    In realtà voglio che ogni processo faccia una pausa random compresa tra 2 e 5 secondi, qui ho fatto solo un esempio, ma allo stesso tempo voglio che non tutti aspettino per lo stesso numero di secondi!
    Nel senso, i figli vengono generati tutti e 5.
    Con il mio codice aspetta tutti e 5 lo stesso numero di secondi, perchè suppongo venga generato lo stesso numero (ad esempio 3) ogni volta che eseguo il programma.
    Capisco che con un intervallo così piccolo non posso sperare che tutti i figli aspettino un numero di secondi differente dall'altro, ma almeno che non creino tutti lo stesso numero!
    Ho provato anche a far generare un numero più alto di 5, ma il risultato è che tutti i figli generano sempre lo stesso numero random! Ecco, io voglio che ogni figlio generi un numero random diverso dagli altri (anche se può capitare con un intervallo piccolo quale quello che interessa a me, che il 1 e il 3 e il 4 figlio generino lo stesso numero).

    A me serve che i figli siano eseguiti in modo concorrente, ma se tutti aspettano per lo stesso tempo, non c'è più concorrenza tra loro. Spero di essermi spiegato.

  4. #4
    Il punto è che la funzione time restituisce il numero di secondi trascorsi dall'1/1/1970 (o qualcosa del genere) e i processi figli vengono creati più o meno nello stesso istante, per cui vai ad inizializzare il generatore di numeri casuali di ogni processo con lo stesso numero.
    Puoi provare a "pescare" un valore casuale da /dev/random: essendo il generatore di numeri casuali condiviso a livello di sistema, ogni processo pescherà il numero successivo della sequenza; in alternativa puoi richiamare srand passandole un contatore più preciso, che sarà quindi differente per ogni processo figlio, eventualmente differenziandolo sicuramente tra un processo e l'altro integrandolo in qualche modo con il PID del nuovo processo.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Ma integrandolo col pid non avrei che il primo processo aspetta un secondo in meno(o in più) del secondo processo, il secondo processo uno in meno(o in più) del terzo eccetera?
    Intendi qualcosa del genere?
    codice:
    sleep((getpid()+rand())%5+2)
    e lo stesso sarebbe con
    codice:
    sleep(rand(getpid())%5+2)
    Non c'è qualche funzione in c che permette di generare numeri casuali che non dipendano dal momento in cui entra in azione il processo (quindi non basandosi sul numero di secondi trascorsi dall'1/1/1970)?

  6. #6
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326
    Guarda mi verrebbe da dirti di risolvere la cosa così (ho eliminato per ora la variabile shm visto che non rientra nel problema)

    codice:
    void child(unsigned int seed)
    {
    	srand( seed );
    	sleep( rand()%5 );
    }
    
    int main(void)
    {
    	unsigned int seed = 0, i;
    
    	for ( i = 0; i < 5; i++ ) {
    		if ( fork() == 0 ) {
    			child(seed);
    			exit(0);
    		}
    		seed++;
    	}
    
    	return 0;
    }
    in sostanza il "seme" non viene generato casualmente, ma varia sequenzialmente da 0 a 5. In alternativa, proprio per rendere più "random" il tutto, puoi generare tale seme con la rand e non inizializzarlo a 0 come faccio io.

    Comunque occhio che per come hai scritto il codice, ciascun processo dopo aver aspettato un certo numero di secondo non muore, ma continua il ciclo, col risultato che ti trovi un numero finale di processi pari a 2^5 - 1, Non so se era questo il tuo scopo, in ogni caso ti ho messo una exit(0) dopo la chiamata a child(), che ovviamente puoi rimuovere.
    every day above ground is a good one

  7. #7
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,315
    Originariamente inviato da peppeocchi
    Ma integrandolo col pid non avrei che il primo processo aspetta un secondo in meno(o in più) del secondo processo, il secondo processo uno in meno(o in più) del terzo eccetera?
    No: un generatore di numeri casuali non funziona così. A seconda del valore con cui esso viene inizializzato, produce una serie diversa di numeri pseudo-casuali. Questo non significa che le sequenze siano "spostate" di una unità.

    Faccio un esempio terra terra: se inizializzi il generatore con il valore X, ottieni una sequenza di numeri pseudo-casuali che potrebbe essere questa

    codice:
    135 - 2 - 744 - 390 - 36 - 1023 ...
    Inizializzandolo con X+1, otterrai una sequenza completamente diversa, ad esempio

    codice:
    45 - 1234 - 34 - 78 - 234 ...
    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  8. #8
    Ok, userò questi metodi "manuali", ma volevo evitarli perchè pensavo ci fosse qualche istruzione che potesse randomizzare il tutto senza che dipendesse da determinati valori....

    Grazie a tutti!

    Ah, questo pezzo di codice fa parte di un esercizio correlato ai semafori, ma magari faccio un altro thread.

    Ciao!

  9. #9
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,315
    Scusa la domanda. Ma è necessario inizializzare il generatore all'interno di ciascun figlio? Perchè non sposti l'inizializzazione sul padre e, a ciascun figlio, passi solamente il valore random risultante?

    In questo modo:
    codice:
    void child(int valore){
      sleep( valore );
    ...
    }
    
    int main(){
       int valoreDaPassare;
       ...
       srand( time(NULL) );
       for(i=0;i<5;i++) {
         valoreDaPassare = rand() % 5;
         if(fork() == 0) child( valoreDaPassare );
       }
    ...
    }
    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

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.