Se tutti i numeri che vengono generati da un processo sono equamente probabili in ogni istante, allora questi numeri sono casuali. Gli utilizzi dei numeri casuali sono molteplici simulazioni,campionatura,analisi numerica,crittografia, programmazione e ad altri ancora. Generare via software numeri casuali con un algoritmo di lunghezza finita non è possibile, per cui sono nati vari algoritmi per generare sequenze numeriche random "pseudocasuali", uno dei primi è il "midlle square" inventato nel 1946 da John von Neumann. Funziona in questo modo, supponiamo di volere generare un numero casuale di 4 cifre, ossia un numero tra 0000 e 9999. Il metodo middle-square richiede come tutti i generatori di numeri pseudocasuali un valore iniziale, detto "seme" dal quale vengono generati i valori successivi. Ad esempio a partire da 1234, elevando tale numero al quadrato abbiamo le otto cifre 01522756 delle quali teniamo solamente le quattro cifre di mezzo 5227. Da queste ripetendo il procedimento otteniamo 27321529 e quindi 3215 e cosi via. Ovviamente la sequenza inizierà a ripetersi una volta che si riavrà il "seme", la lunghezza totale della sequenza fino a riavere lo stesso seme è chiamata "periodo". Per generare sequenze random senza periodo, si devono sfruttare fenomeni fisici non prevedibili come , ad esempio il "rumore" dei dispositivi elettronici. Questo tipo di segnale generalmente ha un andamento nel tempo non descrivibile in maniera analitica, è quindi possibile studiarlo solo in termini statistici. L'idea di base era di sfruttare il rumore generato dal microfono del pc per generare sequenze di bit, e sottoporle a qualche test statistico per verificare se effettivamente la sequenze ottenute erano da considerarsi casuali. Prima di procedere, ho fatto qualche considerazione :
1)Il microfono serve per registrare segnali audio, quindi frequenze fra 20Hz e 20kHz, e taglia frequenze più alte e più basse.
2)Campionando a 8000Hz non potrei comunque analizzare frequenze superiori alla frequenza di Nyquist ovvero superiori a 4000Hz.
3)Visto che per una ricostruzione "leggibile" bisogna campionare almeno a 4 volte la frequenza analizzata, il segnale audio "valido" deve avere al massimo la frequenza di 1000Hz, segnali di frequenza superiore o sono segnali ricostruiti con errori notevoli o sono disturbi.
4)Abbassando al minimo la sensibilità del microfono amplificherei il "rumore" rispetto al segnale utile,e scegliendo di considerare frequenze di 1333Hz(con periodo pari a 6 volte il tempo di campionamento a 8000Hz) potrei aspettarmi che i valori letti siano dovuti al "rumore" e quindi casuali.
Fatte le dovute considerazioni ho scritto questo semplice programmino per linux in c++:
#include <wx/init.h>
#include <wx/string.h>
#include<math.h>
float runtest(float n1,float n0){//calcolo valore runs-test
FILE *fr;
char x,x1;
float valoreatteso=1+2*((n1*n0)/(n1+n0));
float varianzaattesa=((valoreatteso-1)*(valoreatteso-2))/(n1+n0-1);
varianzaattesa=sqrt(varianzaattesa);
fr=fopen("rand-mic.txt", "r");
float contatore=1;
for(int y=0;y<1023;y++){
fseek(fr , y ,0);
x=fgetc(fr);
x1=fgetc(fr);
if(x1!=x)
contatore++;}
float scarto= abs(contatore-valoreatteso);
float diffscarto=2*varianzaattesa-scarto;//con 2 la prob. è 0,95
fclose(fr);
return (diffscarto);
}
int main( )
{
FILE *fd;
FILE *fw;
int x, x1,x2;
int n1=0;
int n0=0;
//registra 2 secondi a 8bit 8000hz
system("arecord -d 2 rand-mic.wav");
//apre il file per il controllo dei bit
fd=fopen("rand-mic.wav", "r");
//apre il file che conterrà la stringa casuale 1024 0/1
fw=fopen("rand-mic.txt", "w");
fseek(fd , 44,0);//salta i primi 44 byte intestazione file wav
while(!feof(fd)){
x=fgetc(fd);
x1=fgetc(fd);
x2=fgetc(fd);
if((x1-x)>0 && (x1-x2)>0){
fputc('1',fw);
n1++;}
if((x1-x)<0 && (x1-x2)<0){
fputc('0',fw);
n0++;}
if(n1+n0==1024)// esce quando la sequenza è lunga 1024
break;
}
printf("numero segni 1 %d", n1);
printf("numero segni 0 %d", n0);
// monobit test n1+n0>100 e ind>0.05 per passare test
float ind=abs(n1-n0)/sqrt(n1+n0);
ind=ind/sqrt(2);
fclose(fd);
fclose(fw);
//chiama funzione controllo run test se ind1>0 prob=0.95
float ind1=runtest((float)n1,(float)n0);
printf("monobit test = %f", ind);
printf("runs test = %f", ind1);
return 0;
}
Il programma scrive in un file di testo una sequenza di 1024 segni 1/0 e poi sottopone l'intera sequenza a 2 test per valutarne la casualità. Il primo test è il monobit-test che valuta il numero di 1/0, questo test da come risultato un valore numerico che se è superiore a 0,05 considera la sequenza casuale. Il secondo è il runs-test che valuta la frequenza delle variazioni 1/0 e 0/1(per approfondire leggere qui http://it.wikipedia.org/wiki/Test_dei_run) questo test da come risultato la differenza fra 2 volte lo scarto atteso e il valore assoluto dello scarto rilevato, se è maggiore di 0 significa che il 95% delle sequenze casuali rientrano in questo range.
Nessun commento:
Posta un commento