Newsgroup: it.comp.lang.c++
Titolo: srand(?) e time (?) sotto Linux

Sto implementendo un proggramma che associa queste due funzioni nel
seguente modo:
 a=(srand(time(0))%6)
che dovrebbe darmi un numero a caso tra 1 e 5.
Ma il compilatore mi dice che non ciene igniorato un valore void .
Chi sa spiegarmi cosa devo fare.
Grazie.

Ti consiglio le faq del NG.
Ciao.
Ps: il fatto che usi gcc o g++ non cambia le cose....
-- 
Posted from 
laguna.tiscalinet.it
 [195.130.224.86] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Scusa nonmi ero accorto che già ti avevo dato lo stesso consiglio...
-- 
Posted from 
twingo.tiscalinet.it
 [195.130.224.85] 


 ha scritto nel messaggio
news:39E88CA6...@libero.it...

Hai fatto un poco di confusione.
Con srand(time(0)) inizializzi il generatore
di numeri casuali.
Per ottenere dei numeri casuali devi fare
a = rand() % 6
(Comunque se ti servono numeri 'molto' casuali è sconsigliabile
usare rand() % 6, anzi è meglio non usare proprio rand)
Manlio Perillo

usare rand() % 6, anzi è meglio non usare proprio rand)
Condivido, "rand() % 6" è un po' inaffidabile. Come già in precedenza
consigliato su questo ng, è meglio:
int a = int (double(rand()/RAND_MAX)*6);
Ciao
Domenico Barra

 writes:

Questo e' un po' *peggio* :-) ...  rand()/RAND_MAX non fa zero?
Ti e' scappato un tasto quando volevi scrivere ((double) rand()/RAND_MAX),
immagino.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it
Murphy's law: "Anything that can go wr
/bin/fortune: segmentation fault - core dumped

 immagino.
Come già scritto da Manlio, usare rand() per generare numeri casuali non ha
molto senso. Esistono decine e decine di algoritmi migliori, anche molto
semplici. Tanto più che generalmente RAND_MAX è un misero 0x7fff.
Usare rand()%6 direi che è *completamente* inaffidabile perché produce una
distribuzione paurosamente non uniforme.
Anche int a=rand()/double(RAND_MAX)*6; (perché non "castate" una costante
anziché il risultato di una funzione?) non è il massimo (anche se è
accettabile per alcuni scopi).
Invece una distribuzione uniforme può essere ottenuta nel seguente modo:
// Ritorna un numero casuale da 0 ÷ n-1
ULONG __fastcall CASU(const ULONG n)
{
 const ULONG S=4294967296./n,X=S*n;
 ULONG x; if(X) { do x=RND_32(); while(x>=X); } else x=RND_32();
 return x/S; // Appena più veloce di x%n
}
RND_32() deve ritornare un numero pseudocasule a 32 bits.
Se rand() ritorna meno di 32 bits (ma più di 16) e se proprio non si vuole
utilizzare una funzione migliore di rand(), RND_32() può essere ottenuta
concatenando due _lrand() così (_lrand() con il compilatore Borland ritorna
31 bits):
_lrand()<<16)|_lrand()&0xFFFF
Cristiano

 ha scritto nel messaggio
news:8sbvbf$h5s$1...@news.mclink.it...

Non sono molto esperto, ma ho letto su Numerical Recipes
(disponibile anche on-line) che a volte quello che può
sembrare 'giusto' non lo è poi tanto, specialmente
nella generazione di numeri casuali.
Inoltre stai usando una funzione che probabilmente è presente
solo sul compilatore della Borland.
Manlio Perillo

 solo sul compilatore della Borland.
E' probabile, ma il mio era solo un esempio. Come ho scritto l'altra volta
esistono decine e decine di algoritmi migliori di rand(). Cercando per il
web se ne possono trovare per tutte le esigenze.
Per esempio la funzione rand() dello standard ANSIC è un semplice generatore
a congruenza lineare e viene implementata nel seguente modo:
y(i) = y(i-1) · 1103515245 + 12345 (mod 2^31)
ed è affetta da una scarsa casualità dei bit meno significativi tanto che
sotto UNIX è stata sostituita da drand48 (con il modulo pari a 2^48).
Questi generatori a congruenza lineare hanno un periodo molto breve se
paragonato ai più recenti generatori come il Mersenne Twister 19937 che ha
l'incredibile periodo di 2^19937 e può essere inizializzato con ben 19937
bit contro i normali 32 dei normali generatori.
Concludendo, ognuno è libero di utilizzare il generatore che vuole perfino
rand()%n, ma si tenga presente che esiste di meglio.
Cristiano

immagino.
Ops, scusami, nella fretta non mi ero accorto che non avevo assegnato il
cast a double all'int restituito da rand (ovvero ho commesso un involontario
errore di parentesi). Credo che dovrò stare più concentrato su quello che
scrivo.
Ciao e grazie
Domenico Barra

risultato non sono perfettamente distribuiti.
Pensi che sia possibile sistemare 11 oggetti in 10 cassetti in modo
piu' uniforme di 1 oggetto per cassetto e un cassetto con due
oggetti ? Grazie ad quella divisione ?
La versione "migliorata" mi sembra tanto buona quanto l'originale
visto che non vedo perche' un generatore basato su rng() che desse una
probabilita' doppia al 5 invece che allo 0 dovrebbe essere considerato
incredibilmente migliore (senza contare che nel caso specifico darebbe
comunque una probabilita' doppia allo zero mancando un +0.5 di
arrotondamento).
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff


E' quello che penso anche io.
Probabilmente a Stefano andrà bene anche l'uso di rand.
Manlio Perillo

 arrotondamento).
Forse sto fraintendendo io o mi ha frainteso tu: io ho scritto "Supponiamo
di avere a disposizione la funzione rng() che generi numeri da 0 a 10
uniformemente distribuiti [...]" per cui non ti riesco a capire quando dici
"[...] rng() che desse una probabilita' doppia al 5 invece che allo 0
[...]".
La distribuzione doppia dello 0 si ottiene facendo rng()%10.
Cristiano

 Probabilmente a Stefano andrà bene anche l'uso di rand.
Probabile, ma se si può utilizzare un generatore migliore praticamente a
costo zero...
Cristiano

La distribuzione doppia dello 0 si ottiene facendo rng()%10.
Ok. Prova a notare come se consideri
   int f(int x) { return x%10; }
   int g(int x) { return int(x/11.0*10); }
   int h(int x) { return int(x/11.0*10+0.5); }
Ottieni:
   x = 0 .. 10
   f() = ( 0,1,2,3,4,5,6,7,8,9,0 )
   g() = ( 0,0,1,2,3,4,5,6,7,8,9 )
   h() = ( 0,1,2,3,4,5,5,6,7,8,9 )
In tutti e tre i casi uno dei numeri ha una frequenza doppia
rispetto agli altri. Inoltre sia nella versione "rude" che
nel tuo "netto miglioramento" il numero a frequenza doppia e'
comunque lo 0. Nota che a mio parere anche la distribuzione
ottenuta da h non e' affatto migliore delle altre due (perche'
5 dovrebbe essere il piu' adatto a ricevere la frequenza doppia ?
... io sto proprio cercando di ottenere l'uguaglianza...).
Se il chi-quadro (o altri test) dicono che h e' migliore allora
ci sono a mio parere dei problemi con quel test. Se addirittura
arrivi a dire che g() e' migliore di f() (nota che generano la
*STESSA* distribuzione di frequenze) allora stiamo diventando
completamente pazzi.
Inoltre come dicevo non avrai mai una distribuzione ottenuta
trasformando *un solo valore di rng* senza memoria che non dia
una frequenza doppia ad uno dei rappresentanti (o peggio).
Questo deriva da quello che in Algebra si chiama "principio
dei cassetti" che dice (in una delle sue forme) che se hai 10
cose e 9 cassetti allora almeno un cassetto contiene due cose.
Ovviamente una distribuzione migliore (anzi perfetta) si ottiene
come avevi fatto notare con il semplice codice
  int w()
  {
    int x;
    while ((x=rng())>9)
      ;
    return x;
  }
Che pero' richiede (un numero arbitrario di) estrazioni multiple
di rng().


 [CUT]
Manlio Perillo

Forse sarebbe il caso di aggiornare le faq su quest'argomento, dopo queste
"rivelazioni"....
A quanto pare generare numeri pseudocasuali interessa a più di una
persona.....
-- 
Posted from 
laguna.tiscalinet.it
 [195.130.224.86] 


 Credo proprio sia il Borland.
No..., non posso crederci!
Non che m'interessi molto (come dicevo io uso solo dei generatori decenti)
ma sembra strano che la versione standard implementata dal compilatore
Borland (che dà solo 15 bits) operi una simile manomissione. Forse tale
disastro è operato a cura della versione long (_lrand() a 31 bits).
Sottoporrò _lrand() ai test di cui dispongo; mi hai incuriosito... ti farò
sapere.
Cristiano


Volendo riscrivere la  funzione in maniera piů generica ho buttato giů:
template <class T, T (*func_random) (void), T max_random>
T NumCasuale (T uprange, T dwrange = 0)
{
    //assert(uprange > dwrange);
    const T range = uprange - dwrange;
    const T rapporto = max_random / range;
    const T scarto = rapporto * range;
    T res = func_random();
    while (res >= scarto) res = func_random();
    return res/rapporto;
}
che, ad esempio, per creare numeri casuali da 0 a 9 si usa cosě:
int a = NumCasuale<int, rand, RAND_MAX> (10);
La domanda č: come posso fare per eliminare la specificazione del tipo di T e a
farglielo dedurre o dal risultato della funzione o dai due parametri? (in modo
da poter scrivere NumCasuale <rand, RAND_MAX> (10) )
Fulvio.

   }
Aridànghete! Continui ad attribuirmi cose che non ho mai scritto! (Perché
mai?)
Quello che scrivi è pura follia (anche se funziona). Se rng() fosse un
generatore da 32 o 48 o ancora più bits potresti aspettare alcuni minuti per
generare un
solo numero!
Quello che ho scritto io (ma che altri hanno inventato) ti consente di
accettare (nel caso di un generatore da 32 bits) tutti i numeri inferiori a
0xFFFFFFFC per ottenere numeri da 0 a 9. Direi che la differenza è
mostruosamente evidente!
Cristiano

 persona.....
L'hai detto.
Cristiano

 da poter scrivere NumCasuale <rand, RAND_MAX> (10) )
Una cosa del genere potrebbe andare bene ugualmente?
#include <iostream>
template <class T>
T NumCasuale (T (*func_random)(), T max_random, T uprange, T dwrange =
0)
{
    //assert(uprange > dwrange);
    const T range = uprange - dwrange;
    const T rapporto = max_random / range;
    const T scarto = rapporto * range;
    T res = func_random();
    while (res >= scarto) res = func_random();
    return res/rapporto;
}
int main()
{
    for ( int i = 0; i < 10; ++i )
        std::cout << NumCasuale( rand, int( RAND_MAX ), 10 ) <<
std::endl;
}
EMG

 ho mai detto!)
Solo f() e g() vanno bene.
h() va bene solo quando RAND_MAX <= 2*MAX, dove MAX e' il massimo
numero richiesto in uscita (nel nostro caso 9).
Quando RAND_MAX > 2*MAX, la funzione restituisce anche numeri 
maggiori di MAX.
La quarta funzione, int(x/10.*9), che chiamo i(), genera numeri
che non sono distribiuti uniformemente.  Si nota subito infatti
che MAX puo' uscire solo se  x == RAND_MAX  e quindi ha una
probabilita' nettamente minore degli altri per valori grandi di
RAND_MAX.
Frequenza di uscita dei numeri in alcuni casi:
RAND_MAX = 10,  MAX = 9   come nell'esempio originale
f()  2 1 1 1 1 1 1 1 1 1 
g()  2 1 1 1 1 1 1 1 1 1 
h()  1 1 1 1 1 2 1 1 1 1 0 
i()  2 1 1 1 1 1 1 1 1 1 
RAND_MAX = 34,  MAX = 9
f()  4 4 4 4 4 3 3 3 3 3      numeri bassi piu' frequenti
g()  4 3 4 3 4 3 4 3 4 3      frequenza "alternata"
h()  2 4 3 4 3 4 3 4 3 4 1    esce anche MAX+1
i()  4 4 4 4 3 4 4 4 3 1      frequenza "anomala"
RAND_MAX = 999,  MAX = 9
f()  100 100 100 100 100 100 100 100 100 100 
g()  100 100 100 100 100 100 100 100 100 100 
h()   50 100 100 100 100 100 100 100 100 100 50 
i()  111 111 111 111 111 111 111 111 111   1 
Nell'ultimo caso sono evidenti gli errori di h() e i(),
e al crescere del rapporto fra RAND_MAX e MAX la situazione
peggiora.
	Mauro



Ma esiste la soluzione definitiva?
Come fa un algoritmo deterministico a generare un dato non
deterministico? Dipende tutto dal 'seed'? Non è un gran che... secondo
me ci vorrebbe qualcosa di 'hardware' che permetta di mappare in una
particolare zona di memoria riservata un 'bit' realmente casuale. Da
li poi.......
Che ne dite?
Luc.

generare un solo numero!
Veramente l'esempio era basato sulla funzione rng concreta
da te espressa. Come noterai ad esempio esiste infatti la
costante 9 e non un generico MAX.
Quello che ho scritto e' *equivalente* al sistema piu'
complesso (e piu' generale) da te descritto quando si
considera il caso concreto da te citato.
Si tratta semplicemente di codice piu' chiaro.


"Luc" <TOGL...@katamail.com-TOGLI> ha scritto nel messaggio
news:ju5tus0ltc2gai9q9...@4ax.com...

Mi sembra di aver letto da qualche parte che la Intel pensa
di 'integrare' un generatore di numeri casuali nei suoi
processori, usando il rumore termico all'interno del chip stesso.
Manlio Perillo

Stiamo parlando due lingue diverse.
Finiamola qui.
Cristiano

 Che ne dite?
Tanti anni fa tentai una cosa del genere basandomi sul rumore bianco ma
il problema del seed veniva semplicemente spostato nel problema della
taratura del punto centrale della banda di ampiezze del segnale. In
pratica non ottenni niente di buono e la distribuzione del bit casuale
era sempre spostata verso una delle due parti.
EMG

 processori, usando il rumore termico all'interno del chip stesso.
Esistono già dei processori Intel per uso crittografico (la serie 8xx) da
abbinare alle varie cpu (Celeron o Pentium II e III) che genera numeri
casuali. Vengono supportati dalle CryptoAPI 2.0. Intel sembra piuttosto
misteriosa circa il tipo di sorgente e gli algoritmi di filtratura
utilizzati.
Comunque l'utilizzare un generatore deterministico è un sistema valido per
molte applicazioni, anche in crittografia purché (utilizzando opportune
tecniche) si riesca a mascherare lo stato del generatore (cioè il valore
numerico che esso contiene) in modo che l'avversario non riesca a risalire o
a prevedere la sequenza di bits generata.
Poi bisogna verificare se il generatore produce effettivamente una sequenza
statisticamente casuale. E a questo scopo esistono decine e decine di test
statistici che però non possono "certificare" un generatore pseudocasuale
come generatore casuale; i test si limitano a confermare che la particolare
sequenza di numeri o di bits (in genere alcuni milioni di bits) ha (o non
ha) dei parametri che deve avere una sequenza casuale.
Mi sono forse dilungato, ma visto che l'argomento suscita un tale
interesse...
Speriamo che prima o poi nasca un ng italiano dedicato alla crittografia e
ai numeri casuali (le due cose sono strettamente correlate).
Cristiano

 era sempre spostata verso una delle due parti.
Non so se dico qualcosa di nuovo, ma tieni presente che tutti i generatori
casuali (o quasi tutti) hanno bisogno di essere sottoposti a de-skewing (che
serve proprio per eliminare il problema che hai accennato) e unbiasing per
ottenere una sequenza veramente casuale.
Cristiano

Salve a tutti,
ciò che sto per scrivere *non* vuole essere una offesa nei confronti di
alcuno (lo premetto per evitare equivoci)... ma è da una settimana che *non*
parlate di C++ ma della problematica alla base della generazionedei numeri
*veramente* casuali.
Mi pare come generare +infinito per il computer. Nessuno di voi ha mai
studiato qualcosa che si chiami "Calcolo Numerico" all'univarsità o sul
posto di lavoro? La morale di questo insegnamento è che qualsiasi cosa si
*implementi* sul computer, anche un supercalcolatore della NASA, è soggetto
sempre ad una approssimazione.
Esistono dei software che realizzano sequenze *quasi* uniformamente
distribuite, ma lo fanno comunque con una approssimazione.
Alla fine, cercando di spaccare il pelo della pulce in 8 non si è capito
quale possa essere una soluzione semplice, veloce, affidabile, *entro un
certo margine di approssimazione* che funzioni.
Insomma, rand() e componenti della stessa premiata ditta fanno pena. E
allora?
Non si pretenderà di accorpare una libreria più grande dell'intero codice
che si ha in mente di sviluppare, solo per generare numeri random.
Io credo, ma ripeto, è solo una mia opinione, opinabile al massimo, che la
soluzione da cercare debba essere "un uovo di Colombo"...
Ho anche letto qualche sciocchezza in merito a "rumore" termico alias rumore
bianco, che *non esiste* se non sulla carta.
Il rumore termico nei circuiti elettronici dipende dalla tecnologia, e da
molti altri fattori quali frequenza, temperatura, distanza tra le metal... e
cosi via.
La soluzione hardware *è* un uovo di Colombo.
:-)
Bye,
Sebastiano.
P.S.
Un povero ignorante che cavolo deve usare al posto di rand()?
P.S. #2 Le FAQ non vi sembrano *poco* FAQ? Io ho letto domande molto più
interessanti, non entry-level come quelle riportate nelle FAQ.
Non è davvero ora di aggiornarle anziche ricopiare sempre la stessa salsa?
;-)

 [CUT]
Scusa l'intervento, ma visto che questo gruppo tratta di C++,
mi sembra inopportuno usare cose (come le macro) di cui
si può fare benissimo a meno.
In questo modo chi legge si fa delle idee sbagliate
(ho visto fin troppi esempi di programmi C++ che non sono
altro che C con classi).
Manlio Perillo


Purtroppo all'epoca ne sapevo abbastanza poco e ora ne so ancora meno.
Quindi non so proprio cosa siano quelle tecniche di cui parli. Magari
l'avessi conosciute a suo tempo quando mi divertivo a fare queste cose.
EMG

RAND_MAX.
Vero ed evidente anche questo. Non avevo notato che in effetti
Cristiano aveva proposto una funzione con quel grosso difetto.
In ogni caso la mia attenzione era catturata da un altro punto:
perche' distribuire gli r elementi con frequenza maggiore sul
range (ma in posizioni fisse) dovrebbe essere meglio che averli
tutti all'inizio ? Questa e' la cosa che non capisco e che
Cristiano non mi vuole spiegare.
Supponiamo ora di essere in un caso piu' interessante di quello
proposto da Cristiano e in cui f() e g() non diano distribuzioni
assolutamente identiche.
Anche secondo te g() e' migliore di f() ? Se si perche' ?


 interessanti, non entry-level come quelle riportate nelle FAQ.
Permettimi una risposta un po' polemica: Le FAQ non son che quello:
domande poste frequentemente, ovvero proprio quelle noiose, entry-level
come dici tu. Lo scopo e' raccoglierle in un posto, in modo che non
intasino il gruppo. Le domande interessanti e' proprio nel newsgroup che
devono stare!
Ciao,
Nicola
P.S. Le FAQ sono state raccolte da Paolo Marotta, che si e' offerto
volontario in un momento in cui aveva il tempo di farlo. Non so se c'e'
qualcuno che ha voglia di impegnarsi ad aggiornarle.

 Anche secondo te g() e' migliore di f() ? Se si perche' ?
Una funzione puo' essere piu' adatta dell'alta per particolari
applicazioni, ma in generale sono equivalenti.
Comunque queste funzioni vanno bene solo se il rapporto fra RAND_MAX
e MAX e' abbastanza grande da rendere trascurabile la differenza di 
probabilita';  negli altri casi e' meglio usare una funzione con
"correzione", tipo   while ((x=rng()) > N);.
g() da risultati migliori quando si usano generatori scadenti che
hanno i bit meno significativi poco casuali (vedi "Numerical Recipes 
in C").
	Mauro

 altro che C con classi).
Per un momento mi ero dimenticato di essere in gruppo di C++, pensavo che
fosse piů utile ed interessante proporre una semplice routine a supporto di
quanto dicevo.
Mi scuso per l'inconveniente.
Cristiano

 Un povero ignorante che cavolo deve usare al posto di rand()?
Qualunque altra cosa :-)
Ne esistono talmente tanti di generatori...
Cristiano

affetto?
Dal fatto che non ne ha infinite!!!
Se rappresenti 10/3 sul calcolatore troverai 3,333....3...
tutti i 3 dopo la virgola che vuoi, anche 10exp9.. ma non potrai mai
rappresentarlo per 10/3 "matematico".
E poi ricordiamoci bene che spesso algoritmi cosi complessi, come quelli
descritti, sono sicuramente *un must* per applicazioni di crittografia, ma
non lo sono per generare una distribuzione di eventi idi tipo modo
gaussiano, ad esempio.
Per esempio, una comune approssimazione di una distribuzione gaussiana è la
somma, iterarta almeno 12 volte, di  numeri rand().
Vi pare strano, ma è cosi che funziona il mondo!!!
:-)
Bye,
Sebastiano


Tratto da /usr/src/linux-2.4.0-pre8/drivers/char/i810_rng.c
Probabilmente si riferisce a piastre matdri intel 8xx
        ----------------------------------------------------------
 
        From the firmware hub datasheet:
 
        The Firmware Hub integrates a Random Number Generator (RNG)
        using thermal noise generated from inherently random quantum
        mechanical properties of silicon. When not generating new random
        bits the RNG circuitry will enter a low power state. Intel will
        provide a binary software driver to give third party software
        access to our RNG for use as a security feature. At this time,
        the RNG is only to be used with a system in an OS-present state.
 
        ----------------------------------------------------------
( solo per completezza di informazioni .... )


Un algoritmo non dipende dal linguaggio utilizzato.
Inoltre un programma C è anche un programma C++
(tranne dele eccezioni).
Il problema è che tu usi delle macro mentre in C++
(ed ora anche in C) si possono usare le funzioni inline,
variabili const o template.
Se chi legge questo newsgroup vede che vengono usate
sempre le macro sarà portato ad usarle anche lui
(lo stesso dicasi per altri cattivi stili di programmazione).
Inoltre ci sono alcuni che scrivono qui pensando che si
discuta di C (e scrivono proprio qui perchè hanno il
Borland C++ od il Visual C++).
Manlio Perillo

Non è davvero ora di aggiornarle anziche ricopiare sempre la stessa salsa?
Quelle faq furono inizialmente raccolte da me con l'aiuto dei
partecipanti del NG che fornirono le risposte da cui io ho fatto un
sunto. Adesso che tra un capitolo e l'altro della tesi, una faccenda
domestica e l'altra, mi ritrovo a lavorare 9 ore al giorno non trovo
piu` il tempo... tanto che non solo ho dovuto passare la palla, ma
anche ridurre enormemente la mia attivita` sul NG e su altri fronti.
Paolo

rappresentarlo per 10/3 "matematico".
Dipende dalla base, in base 3 se non erro e` rappresentabile con 3
cifre. Sono i numeri irrazionali che indipendentemente dalla base non
sono rappresentabili con un numero finito di cifre.
Paolo

 Credo proprio sia il Borland.
Ho sottoposto _lrand() del Borland ai test statistici di cui dispongo
(ricordo che _lrand() genera numeri da 0 a 2^31-1 non so in quale modo).
Per verificare quanto scrivi ho generato numeri a 32 bits utilizzando questi
quattro modi:
1. ((_lrand()<<16)&0xFFFF0000)|(_lrand()&0xFFFF);
2. ((x<<16)&0xFFFF0000)|(x&0xFFFF);
3. (_lrand()<<1)&0xFFFF0000|(_lrand()>>15);
4. (x<<1)&0xFFFF0000|(x>>15);
le prime due espressioni utilizzano i 16 bits meno significativi mentre le
seconde due quelli più significativi (x è un ULONG che viene posto uguale a
_lrand() in modo da utilizzare i bits dello stesso numero).
Se quanto dici è vero ci si dovrebbe aspettare risultati peggiori dalle
seconde due espressioni che utilizzano i bits meno significativi del
generatore originario (non _lrand()).
I test DiehardC, NIST ed altri test minori non evidenziano comportamenti
anomali con le espressioni 1 e 3, mentre dànno risultati pessimi con le
espressioni 2 e 4; tuttavia con l'espressione 4 i risultati sono veramente
disastrosi.
Questo significa che hai alte probabilità di aver ragione.
E' veramente difficile credere che dei professionisti che scrivono un
compilatore compiano tali pazzie!
Grazie a Manlio abbiamo trovato un motivo in più per non utilizzare rand() e
compagnia.
Cristiano

 grandi.
A completamento di quanto detto tre giorni fa, in effetti facendo alcune
prove variando i parametri, si ottengono sequenze di bits molto diverse pur
ottenendo lo stesso chi-quadro calcolato sui numeri.
Questo solo per sottolineare che le distribuzioni *sono* nettamente
differenti. Se interessa a qualcuno...
Cristiano

generare un solo numero!
Tu:
"Veramente l'esempio era basato sulla funzione rng concreta
da te espressa. Come noterai ad esempio esiste infatti la
costante 9 e non un generico MAX.
Quello che ho scritto e' *equivalente* al sistema piu'
complesso (e piu' generale) da te descritto quando si
considera il caso concreto da te citato.
Si tratta semplicemente di codice piu' chiaro."
Cosa stai dicendo!?
Quello che ho scritto io e che riporto per comodità
ULONG __fastcall CASU(const ULONG n)
{
 const ULONG S=4294967296./n,X=S*n;
 ULONG x; if(X) { do x=RND_32(); while(x>=X); } else x=RND_32();
 return x/S; // Appena più veloce di x%n
}
è *completamente* differente da quello che scrivi tu (per fortuna!).
Per generare un numero da 0 a 9 con il tuo sistema (se RNG_32() ritorna
numeri a 32 bits) vengono scartati ben 4 miliardi e 295 milioni di numeri
(!). Con il mio sistema vengono scartati soltanto 5 numeri (!).
Non parliamo del resto della tua risposta...
Quando dici di essere testardo io credo che tu lo sia a tal punto da non
poter nemmeno ragionare su quello che ti viene proposto; almeno questo è ciò
che dimostra il tuo modo di replicare a quello che ti si dice con esempi
completamente diversi da quelli che ti vengono portati.
Cristiano

 [CUT]
Ci sono molti controesempi a quello che dici,
in particolare dalla descrizione fisica di un fenomeno.
Non proseguo per manifesto OT.
Manlio Perillo


Dovresti ringraziare gli autori di Numerical Recipes.
Se vuoi sapere *cosa* fa _lrand puoi sempre leggerti il
codice sorgente (con il Borand C++ 5.02 --free-- è presente).
Il problema è che molti programmatori non sono anche esperti
di calcolo numerico.
Infatti usano sempre i double (mentre è più coerente usare
float) e fanno cose come questa.
Anche gli Standard per il C ed il C++ sono essenzialmente
stati sviluppati senza la 'consulenza' di esperti di calcolo
numerico (anche se sembra che le cose stiano cambiando).
Manlio Perillo

 somma, iterarta almeno 12 volte, di  numeri rand().
Cosa significa?
Cristiano

 codice sorgente (con il Borand C++ 5.02 --free-- è presente).
Intendi il codice sorgente di tutto il compilatore? Quanti mega saranno?
Cristiano

 ha scritto nel messaggio
news:8ssjj6$loi$1...@news.mclink.it...

Ovviamente no.
Il codice sorgente del compilatore non è disponibile.
Intendevo il codice sorgente della libreria.
In particolare il file rand.c.
Te lo posterei ma credo sia illegale.
P.S.
Approfitto dell'occasione per chiederti se conosci la
libreria libgpp.
Sono presenti delle classi per generare numeri casuali.
La cosa più interessante è che ci sono due metodi
per convertire una (o due) WORD di bits casuali
in un float o double compreso fra 0 e 1.
I files sono RNG.h e RNG.cc
(di questo potremmo anche parlare in privato)
P.S. 2
Nella documentezione della libstdc++ c'è scritto
che la libreria libgpp non è più supportata perchè
contiene cose non previste dallo Standard.
Che COSA ASSURDA.
Se c'è questa mentalità stiamo freschi.
E pensare che il movimento GNU potrebbe dare molto
al C++ (e viceversa)
Manlio Perillo

....qui non ci si può permettere di dire sciocchezze...
grazie Paolo, hai colto nel segno !!!
L'esempio è effettivamente sbagliato, ma casi in cui si perde di precisione
ce ne sono a tonnellate...
:-)
Sebastiano

completamente diversi da quelli che ti vengono portati.
Il problema e' che non mi hai convinto. Personalmente la mia
convinzione attuale e' che nella tua testa ci sia un po' di
confusione oltre ad un notevole disprezzo nei miei confronti.
Sia l'una che l'altra cosa mi lasciano comunque abbastanza
indifferente. Resto in ogni caso a disposizione (anche e
*soprattutto* per mail) se dovessi avere qualche argomento che
supporti la tua posizione che riassumo in:
 - si supponga di avere un generatore casuale uniforme
   rng() che restitituisce numeri fra 0 e 10
 - l'uso di "rng()%10" per ottenere numeri fra 0 e 9 e'
   una pessima scelta. Meglio e' utilizzare la mitica
   formula "rng()/11.*10" (anzi... "rng()/10.*9").
   Questa formula e' nota per avere anche effetti
   terapeutici contro la gotta e per poter trasformare
   il piombo in oro.
   Chi non ci crede e' pregato di andarsi a leggere i
   newsgroup di crittografia dove non si parla d'altro
   visto che la mia evidente autorevolezza mi autorizza
   a fare qualunque affermazione senza che io sia tenuto
   a giustificarla.
   La pena per chi contravviene e' l'insulto in pubblica
   piazza.
Scherzi a parte se vogliamo invece citare letteralmente tu
hai scritto (secondo deja)
"
Facendo rng()%10 otteniamo numeri da 0 a 9 ma lo zero ha una
probabilità di uscire che è doppia rispetto agli altri numeri,
infatti lo zero esce quando rng() ritorna 0 o 10.
Un simile generatore fallisce ogni tipo di test statistico sui
numeri pseudocasuali ed è il peggiore che possa esistere.
 
Un discreto miglioramento si ottiene effettuando la riduzione
per il modulo che nel caso di rand() equivale al consueto
rand()/double(RAND_MAX)*n. In questo caso, però, si ha un
certo "rumore di conversione" cioè i bit del risultato non
sono perfettamente distribuiti.
"
Questa affermazione e' gratuita e non giustificata (la
funzione "discretamente migliorata" offre la stessa
distribuzione statistica visto che lo zero esce quando
rng() ritorna 0 oppure 1).


altro che C con classi).
Mi spiace vedere che disprezzi il "C con classi". Secondo
me si tratta di un ottimo compromesso fra semplicita'
efficienza e duttilita'.
Chi pensa che il "C con le classi" non abbia un suo spazio
(ora e in futuro) a mio parere sbaglia di grosso.


sono rappresentabili con un numero finito di cifre.
non ci avevo mai pensato! Certo che la matematica non finisce mai di
stupirmi. Mi rendo conto che è OT, però è possibile una base sqrt(2)
oppure PIgreco, o e? In questo modo anche gli irrazionali possono
essere rappresentati( es. sqrt(2) in base 10 è uguale ad 1 in base
sqrt(2) ).
Anto

 sqrt(2) ).
Credo di si.
Tuttavia non escludo ci possano essere teoremi che presuppongono una basa intera.
Comunque... se usi una base irrazionale per rappresentare con un numero finito di cifre un numero irrazionale... va a finire che tutti i numeri interi e razionali diventano ad un numero infinito di cifre...
Inoltre ogni altro numero irrazionale (apparte multipli e frazioni della base) avrebbe ancora un numero infinito di cifre. 
Non mi pare vantaggioso. Trovi?
_______________________________________
 Luca Minudel   Consulente Informatico
 
luca.m...@nline.it
 Conegliano (TV)
 WWW    
http://www.nline.it/consulting


Io c'è l'ho solo con le macro
(e al loro abuso  ~~ come gli antibiotici -:) ~~).
Manlio Perillo

 sono rappresentabili con un numero finito di cifre.
O anche 
class Rational {
  public:
    Rational(int nn, int dd) : n(nn),d(dd) {}
    getNumerator() { return n; }
    getDenominator() { return d; }
  private:
    int n;
    int d;
};
L'implementazione degli operatori e' lasciata come esercizio al lettore
;-)
Ciao,
Nicola
P.S. Cosi' Manlio e' contento...

 Non mi pare vantaggioso. Trovi?
Non lo so per certo, ma non mi convince. Il punto fondamentale e' che la
distinzione tra numeri razionali e numeri irrazionali e' la
rappresentabilita' con un numero finito di cifre: intuitivamente non
vedo come se ne possa usare un numero frazionario o addirittura
irrazionale.
Pero' e' anche un problema di convenzioni: potremmo inventare una nuova
unita' di misura, il Pitagora, definito come la diagonale di un quadrato
il cui lato e' lungo un metro. Questo ci consentirebbe di rappresentare
esattamente tutti quei numeri che hanno rapporto radice di 2 rispetto
alle misure esatte del sistema metrico decimale.
Ciao,
Nicola

questo interessa solo agli studenti universitari
Cioe' stai dicendo che se i generatori di numeri casuali non sono
tanto casuali e' un problema, mentre che se il rumore di fondo
utilizzato per generare numeri casuali non e' troppo casuale e' un non
problema?
-- 
Tieni per te il Papero se vuoi la mia email
Sito Papero -> 
http://utenti.tripod.it/papero

 al C++ (e viceversa)
Ai tempi in cui programmavo su Amiga1200 con il compilatore GNU mi sono
fatto un'ottima idea di tale compilatore. Anche nelle riviste del settore
informatico se ne faceva un bel parlare. Non sono molto certo del
"viceversa"; ma non sono esperto come te in questo campo.
Cristiano

 rng() ritorna 0 oppure 1).
Questo è vero per il semplice esempio che ho portato. Ma serviva solo per
mettere bene in evidenza che lo 0 esce il doppio delle volte rispetto agli
altri numeri.
Puoi notare che il secondo paragrafo l'ho ben diviso dal primo e che compare
una generica n. Così facendo intendevo uscire dal banale esempio per
generalizzare la cosa.
Utilizzando la riduzione per il modulo noterai che la distribuzione dei bit
è diversa da rand()%MAX (in generale). Questo potrebbe avere come
conseguenza una migliore distribuzione sui bits che non si ottiene con
rand()%MAX.
Comunque il problema di fondo nell'utilizzare rand()%MAX rispetto alla
riduzione per il modulo risiede nell'utilizzare i bits meno significativi
che hanno "scarsa casualità" nella maggior parte dei generatori, come ha
fatto notare Mauro:
"g() da risultati migliori quando si usano generatori scadenti che
hanno i bit meno significativi poco casuali (vedi "Numerical Recipes
in C")."
In realtà mi permetto di aggiungere che quasi tutti i generatori (anche i
migliori) hanno i bits meno significativi poco casuali (o comunque meno
casuali degli altri).
Ovviamente la cosa migliore da fare per togliersi ogni dubbio è utilizzare
la semplice routinetta già vista che non dà adito a dubbi.
Per la verità per generare un numero intero da 0 a n ci sarebbe anche la
formuletta x=(n+1)*rand()/RAND_MAX (sempre da "Numerical Recipes") che dà x
distribuite esattamente come lo sono i numeri di rand(), ma si può incappare
in evidenti problemi di overflow.
Cristiano

sqrt(2) ).
L'irrazionalita` di certi numeri discende unicamente dagli assiomi
alla base della matematica (quella cui comunemente facciamo
riferimento).
Non credo quindi che sia possibile "far sparire i numeri irrazionali"
(qualcuno l'avrebbe gia` fatto)...
Paolo

 Nicola
Questa mi sembra proprio una cosa che non sta ne' in cielo ne' in terra
ne' in Q...
A meno che tu non volessi accennare alla possibilita' di estendere il
corpo dei razionali a (Q * (1 + sqrt(2))), lo stesso processo che
permette di estendere R a R * (1 + i)... Ma ti sara' senz'altro chiaro
che le combinazioni lineari (naturalmente a coefficienti razionali!) con
trascendenti non sono chiuse rispetto al prodotto ( ne' lo sono la quasi
totalita' delle combinazioni lineari di numeri irrazionali). 
Ma non so se volevi accennare a questo, puoi spiegare meglio a cosa ti
riferivi?

Gia'. Lo pseudo rumore bianco va analizzato rispetto alle sue
caratteristiche di "casualita'" e non preso per buono a priori. Mi pare
interessante invece la segnalazione di Goffredo Baroncelli di qualche
giorno fa circa l'esistenza di generatori di numeri casuali basati su
proprieta' quantistiche.
Ciao,
Nicola

Al fatto che, visto che siamo informatici, il punto fondamentale non e'
se si possono rappresentare i numeri irrazionali con una notazione
finita (e non si puo'), ma a cosa serve questa eventuale notazione
finita: come gia' indicato altrove, per alcuni irrazionali esiste gia'
una notazione finita (ad es. e, pi, ma anche la notazione che usa il
segno di radice).
Ciao,
Nicola Musatti

 problema?
Già (come ha detto saggiamente Nicola). Vorrei solo aggiungere qualcosa.
Che io sappia non esiste un rumore bianco che preso così com'è sia valido
per generare numeri casuali.
Tutte le sorgenti utilizzate per generare numeri casuali (non pseudocasuali)
hanno bisogno di filtri per ottenere sequenze di bits statisticamente
casuali.
Per capire meglio i numeri casuali, un giorno ho collegato un micronofo alla
scheda audio e l'ho messo fuori dalla finestra nell'ora di punta; quindi non
ho usato il rumore bianco della scheda, che nel mio caso non è rilevabile
(sound blaster gold).
E' ovvio che in numeri generati in questo modo sono completamente casuali:
non è assolutamente possibile prevedere il momento in cui passa l'autobus,
il muratore accende il martello pneumatico, passa il motorino ad una data
velocità e numero di giri del motore, e quant'altro. Inoltre non è neanche
possibile prevedere l'intensità di tali rumori. Per cui i numeri così
generati sono assolutamente casuali. Tuttavia un generatore di questo tipo è
molto probabile che fallisca buona parte dei test statistici (come dici tu
simpaticamente "non è troppo casuale").
Fortunatamente questo non è un problema perché filtrando opportunamente i
bit, il generatore darà una sequenza veramente casuale e imprevedibile
dotata anche di ottime caratteristiche statistiche, cioè i bit a 0 sono
circa quanto quelli a 1, non ci sono ammassamenti di bit a 0 o a 1, ecc.
Infatti applicando un semplice filtro la sequenza è sempre casuale e
statisticamente ottima: basta scartare i due bits consecutivi a 00 o a 11e
prendere solo il primo (o il secondo) bit delle coppie 10 e 01. Concatenando
i bit, si otterranno i numeri voluti.
Ovviamente esistono sistemi più complessi e affidabili.
Cristiano