Esempio di utilizzo della funzione per generare numeri casuali






// inizio file     myrand.h

#include <stdlib.h>

int int_rand(int,int); // generatore di numeri casuali di tipo intero

double doub_rand(double,double)
; // generatore di numeri casuali di tipo double


int int_rand(int min,int max)
{int numero_casuale;
 int differenza;
 differenza = (max - min) + 1;
 numero_casuale = rand() % differenza ;
 numero_casuale = numero_casuale + min ;
 return numero_casuale;
}

double doub_rand(double min,double max)
{double numero_casuale,differenza;
 differenza = (max - min);
 numero_casuale = ((double) rand() /RAND_MAX) * differenza;
 numero_casuale += min ;
 return numero_casuale;
}

// fine file     myrand.h



// inizio file sorgente

#include <stdio.h>
#include "myrand.h"


int main()
{int num,min,max;
  srand(23847924);            // il compilatore, dove trova la dichiarazione di questa funzione ?
 min = 30;
 max = 50;
 printf("\ngenero un numero casuale compreso tra %d e %d\n",min,max);
 num = int_rand(min,max);
 printf("\n %d e\' compreso tra %d e %d\n",num,min,max);

 return 0;}



// fine file sorgente








funziona ancora tutto con la seguente implementazione ?

// inizio file     myrand.h

...
int int_rand(int min,int max)
{
 int differenza;
 differenza = (max - min) + 1;
 max = rand() % differenza ;
 max = max + min ;
 return max ;
}


...

// fine file     myrand.h


// inizio file sorgente

#include <stdio.h>
#include "myrand.h"


int main()
{int num,min,max;
  srand(23847924);
 min = 30;
 max = 50;
 printf("\ngenero un numero casuale compreso tra %d e %d\n",min,max);
 num = int_rand(min,max);
 printf("\n %d e\' compreso tra %d e %d\n",num,min,max); // stampa ancora i valori corretti ??

 printf("il valore della differenza tra min e max e\' %d",differenza); // cosa stampa ?

 return 0;}


// fine file sorgente





Prima di proseguire apriamo una piccola parentesi sulla rappresentazione binaria dei caratteri. Prendiamo come riferimento il carattere 'y'. Il codice ASCII di questo carattere è il 121 e questo valore, in rappresentazione binaria, risulta pari a 01111001. La sequenza di bit si legge in questo modo:

2^7
2^6
2^5
2^4
2^3
2^2
2^1
2^0
0
1
1
1
1
0
0
1


121 = 01111001 = 0 * 2^7 + 1 * 2^6 + 1 * 2^5 + 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 1 * 2^0


Come faccio a determinare qual è il valore del primo bit a destra ? Il primo bit di destra indica se, nella rappresentazione del numero in potenze di 2, compare anche il termine corrispondente alla potenza di ordine 0, ovvero di 2^0 (= 1). Se quindi il numero è pari tale contributo non compare, viceversa se il numero è dispari tale contributo è presente.

Determinare il valore del primo bit equivale perciò a determinare se il numero sia pari o dispari, informazione che possiamo ricavare a parire dalla divisione per 2 con resto intero. In conclusione, dato un numero intero num, il valore

num % 2

rappresenta il valore del primo bit a destra della sua rappresentazione binaria.






Supponiamo ora di dividere il numero per una potenza di 2, ad esempio per 2^3

121 / 2^3 = (0 * 2^7 + 1 * 2^6 + 1 * 2^5 + 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 1 * 2^0 ) / 2^3

= 0*2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0 + 0*0 + 0*0 + 1*0



Gli ultimi valori sono zero perché il rapporto risulta uguale ad un numero decimale inferiore a 1 rappresentato come un intero (dato che le potenze di 2 sono numeri interi).


Alla fine, quindi, ci rimane

121 / 2^3 = 0 * 2^4 + 1 * 2^3 + 1 * 2^2 + 1 * 2^1 + 1 * 2^0 = 15

2^7
2^6
2^5
2^4
2^3
2^2
2^1
2^0
0
0
0
0
1
1
1
1



NOTA : la rappresentazione binaria del numero è pari a quella del valore iniziale, spostata verso destra di tre posizioni ! Ogni divisione per 2 equivale ad uno spostamento a destra dei bit.


Questo ci permette di capire perché il valore di 1 / 2 (rappresentati come interi) sia 0 e non 0.5 !


Se ora eseguo una divisione per 2 con resto intero ottengo il valore del primo bit a destra; ma tale valore, dato che abbiamo appena eseguito uno spostamento a destra della sequenza di bit di 3 posizioni non rappresenta altro che il valore del bit che stava nella quarta posizione della rappresentazione binaria del numero originale.

Abbiamo quindi trovato un metodo che ci permette di visualizzare il valore di ogni singolo bit di cui è composta una variabile di tipo intero o char. Ovvero, per visualizzare il bit che si trova nella posizione corrispondente alla potenza di 2 di ordine nè sufficiente dividere il numero per la corrispondente potenza di 2 e poi calcolare il resto della divisione per 2.

Ad esempio:

num = 3423 = 00000000000000000000110101011111

se voglio il bit corrispondente alla potenza di ordine 6, ovvero il settimo bit da destra, devo dividere per 2^6 (= 64)

3423 / 64 = 53
53 % 2 = 1





Costruiamo ed analizziamo ora un programma che impieghi le funzioni utili a generare numeri casuali e stampi uno dei bit delle variabili.

Esercizio:

(1) chiedere all'utente di inserire due caratteri qualsiasi;
(2) usare tali caratteri per inizializzare il generatore di numeri casuali utilizzando la funzione srand()
(3) generare un numero compreso tra 48 e 57 (ovvero il codice ASCII di un carattere numerico)
(4) stampare il carattere corrispondente
(5) nel caso il carattere sia '5', stampare una scritta che notifichi all'utente la cosa e calcolare il quadrato del numero rappresentato dal carattere
(6) far generare un secondo numero casuale compreso tra 9.85 e 11.05
(7) elevare al quadrato tale valore casuale e stampare a video il carattere corrispondente ed il suo codice ASCII
(8) stampare il terzo bit di tale carattere




Per preparare il codice mi servono:



(1) due variabili di tipo char ed una di tipo double
(2) stdio.h e printf per visualizzare i messaggi
(3) myrand.h e srand() per generare numeri casuali


// inizio file sorgente

#include <stdio.h>
#include "myrand.h"



int main()
{char car1,car2;
 double numero;
 printf("\n inserire, uno di seguito all'altro, due caratteri");
 car1 = getchar();
 car2 = getchar();
 srand(car1*car2); // inizializzo il generatore di numeri casuali
 car1 = int_rand(48,57);
 printf("\n\nil carattere ottenuto e\': %c",car1);

 if(car1 == '5')
    {printf("\n il carattere casuale e\' pari a %c",car1);
      printf("\n il quadrato del numero corrispondente, %d, vale %d",car1-'0',(car1-'0')*(car1-'0'));
    }

 numero=doub_rand(9.85,11.05);

 printf("\nil numero casuale ottenuto e\' %f",numero);

 numero *= numero; // elevo al quadrato

 printf("\n il suo quadrato vale %f",numero);

 printf("\n il carattere corrispondente vale %c ed il codice ASCII e\' %d",(int) numero,((int) numero)%256);

// perché serve il cast esplicito ? non era sufficiente lo specificatore di formato ??

 printf("\n il terzo bit del carattere vale %d",( (((int) numero) % 256) / (2*2) ) %2);

 return 0;}



// fine file sorgente