[C] Utilizzo di rand()

Messaggioda utente__medio » 28/02/2024, 22:09

Per ottenere un numero casuale nell'intervallo \( [ 0 \ ; \ n ) \) si utilizza di solito la formula rand() % n, ma riflettendo, oltre al fatto che bisognerebbe controllare che \( n \leq RAND_{MAX} + 1 \), mi sono reso conto che solo in alcuni casi la suddetta formula fornisce una distribuzione uniforme, ossia quando \( RAND_{MAX} + 1 = k \cdot n \) con \( k \in N^+ \).

Per esempio ipotizzando \( RAND_{MAX} = 15 \) e \( n = 7 \)

Codice:
 0 % 7 = 0
 1 % 7 = 1
 2 % 7 = 2
 3 % 7 = 3
 4 % 7 = 4
 5 % 7 = 5
 6 % 7 = 6
 7 % 7 = 0
 8 % 7 = 1
 9 % 7 = 2
10 % 7 = 3
11 % 7 = 4
12 % 7 = 5
13 % 7 = 6
14 % 7 = 0
15 % 7 = 1

avremmo

$p(0) = p(1) = 3/(RAND_(MAX)+1) = 3 / 16$
$p(2) = p(3) = p(4) = p(5) = p(6) = 2 / 16$

Magari poi penso a qualcosa di più raffinato, ma nel frattempo dal momento che non so come funzioni rand() dietro le quinte, mi chiedevo se un approccio rudimentale come il seguente restituisca o meno una distribuzione uniforme:

Codice:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

unsigned int my_rand(unsigned int n)
{
    if(n > RAND_MAX + 1)
    {
        return n;
    }
    if(!((RAND_MAX + 1) % n))
    {
        return rand() % n;
    }
    unsigned int r;
    for(unsigned int a = RAND_MAX / n * n; (r = rand()) >= a;);
    return r % n;
}

int main()
{
    srand(time(0));
    printf("%u\n", my_rand(37));
}
"Ci abbaiano, Sancho; segno che stiamo cavalcando!"
utente__medio
Junior Member
Junior Member
 
Messaggio: 334 di 394
Iscritto il: 02/11/2021, 12:48
Località: Draghistan

Re: [C] Utilizzo di rand()

Messaggioda Quinzio » 29/02/2024, 07:56

Direi che va bene, fa quello che deve fare.
In rete trovi tutto su come funzionano quelle funzioni pseudo-causali tipo la rand.
Pero' non so se ne vale la pena, bisogna spenderci del tempo e dipende da cosa devi fare.
Quinzio
Cannot live without
Cannot live without
 
Messaggio: 5882 di 10547
Iscritto il: 24/08/2010, 06:50

Re: [C] Utilizzo di rand()

Messaggioda apatriarca » 29/02/2024, 22:42

rand è una pessima funzione per generare numeri casuali e l'espressione rand() % n non genera numeri uniformi come hai già osservato. Se è importante generare "buoni" numeri casuali, è meglio utilizzare altre funzioni (non standard).
apatriarca
Moderatore
Moderatore
 
Messaggio: 5803 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Utilizzo di rand()

Messaggioda utente__medio » 29/02/2024, 23:27

Quinzio ha scritto:In rete trovi tutto su come funzionano quelle funzioni pseudo-causali tipo la rand.
Pero' non so se ne vale la pena, bisogna spenderci del tempo e dipende da cosa devi fare.

In effetti in rete si trova parecchio materiale sulla generazione di numeri pseudo-causali, oltre al fatto che ho letto che esistono librerie apposite per operazioni di questo tipo.
Alla fine lo scopo del topic era più che altro ragionare su un utilizzo più ponderato della classica rand().


Quinzio ha scritto:Direi che va bene, fa quello che deve fare.

In fin dei conti quello che ho implementato è una sorta di estrazione con rimessa ridotta al minimo.


apatriarca ha scritto:l'espressione rand() % n non genera numeri uniformi come hai già osservato

Magari poi rifletto anche su un possibile approccio senza "tentativi".
"Ci abbaiano, Sancho; segno che stiamo cavalcando!"
utente__medio
Junior Member
Junior Member
 
Messaggio: 335 di 394
Iscritto il: 02/11/2021, 12:48
Località: Draghistan

Re: [C] Utilizzo di rand()

Messaggioda apatriarca » 05/03/2024, 11:21

L'approccio che scarta i valori è quello più uniforme. La principale ragione è che non c'è alcun modo di suddividere RAND_MAX valori in N blocchi della stessa dimensione se N non divide RAND_MAX. Ci sarà sempre qualche blocco che sarà maggiore o minore degli altri.
apatriarca
Moderatore
Moderatore
 
Messaggio: 5805 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid


Torna a Informatica

Chi c’è in linea

Visitano il forum: Google Adsense [Bot] e 1 ospite