| ZER DAKIDAN: Ariketa 19 | Zenbakien funtzio estandarrak artikulua ikusi genuen. ZER IKASIKO DUDAN: Berriro ikusiko ditugu rand() eta srand() funtzioak eta RAND_MAX makroa. |
Sorta aleatorioak baino sasi aleatorioak dira ikasiko ditugun zenbakien multzoak. Zenbakiok sasi aleatorioak dira haien sorreran algoritmo bat jarraitzen delako.
C lengoaian, zenbaki aleatorioak lortzeko, rand() funtzioa dago. Funtzio honek ez du parametrorik behar eta deitzen diogun bakoitzean 0 eta RAND_MAX arteko ausazko zenbaki oso bat itzultzen digu. Bai rand() funtzioa eta RAND_MAX makroa stdlib.h liburutegian definiturik daude.
RAND_MAX zenbakiren balioa desberdina izan daiteke C lengoaiaren bertsio batetik bestera, izan ere bere balioa stdlib.h liburutegiaren ezarpenaren araberakoa da, baina gutxienez 32767 balioko du. Beraz, rand() funtzio estandarrak, 0 eta 32676 arteko balio bat itzuliko dio modulu deitzaileari (0 eta 32676 biak barne).
Ondoko programa honetan zortzi zenbaki aleatorio lortzen dira birritan. Non, lehen for aginduan iZbk zenbaki aleatoriotik abiatuta 0 eta 5 arteko iZbkEskalatua zenbaki aleatorioa lortzen den, eta iZbk zenbaki aleatoriotik abiatuta 0.0 eta 0.99 esparruko fZbk zenbaki aleatorioa lortzen den:
/* 7a-ZenbakiAleatorioak: rand() funtzioa eta RAND_MAX makroa */
// 8 zenbaki oso sortu eta pantailaratu eskalatu gabe eta eskalatuta: [0, 5] eta [0.0, 0.99]
// 8 zenbaki oso sortu eta pantailaratu eskalatu gabe eta eskalatuta: [17, 21] eta [14.55, 19.66]
#include <stdio.h>
#include <stdlib.h> // rand() funtziorako eta RAND_MAX makrorako
#define iMIN 17 // behemuga
#define iMAX 21 // goimuga
#define fMIN 14.55 // behemuga
#define fMAX 19.66 // goimuga
int main()
{
int iKont;
int iZbk, iZbkEskalatua;
float fZbk;
printf("\nRAND_MAX = %d", RAND_MAX);
printf("\nrand() >>> [0, %d] biak barne\n", RAND_MAX);
printf("\n rand() %%6 / RAND_MAX");
printf("\n ----- ---------- ------ ----------");
printf("\n iKont [0, 32676] [0, 5] [0.0, 1.0]");
printf("\n ----- ---------- ------ ----------");
for (iKont=1; iKont<=8; iKont++)
{
iZbk = rand(); // zenbaki aleatorioa sortu
iZbkEskalatua = iZbk % 6; // 0 eta 5 artekoa
fZbk = (float)iZbk/RAND_MAX; // 0.0 eta 0.99 artekoa
printf("\n %5d %13d %12d %16f", iKont, iZbk, iZbkEskalatua, fZbk);
}
printf("\n");
printf("\n rand() %% + / RAND_MAX * +");
printf("\n ----- ---------- -------- --------------");
printf("\n iKont [0, 32676] [%d, %d] [%.2f, %.2f]", iMIN, iMAX, fMIN, fMAX);
printf("\n ----- ---------- -------- --------------");
for (iKont=1; iKont<=8; iKont++)
{
iZbk = rand(); // zenbaki aleatorioa sortu
iZbkEskalatua = iZbk % (iMAX-iMIN+1) + iMIN; // iMIN eta iMAX artekoa
fZbk = (float)iZbk/RAND_MAX*(fMAX-fMIN) + fMIN; // fMIN eta fMAX artekoa
printf("\n %5d %14d %11d %19.7f", iKont, iZbk, iZbkEskalatua, fZbk);
}
printf("\n");
return 0;
}
![]() |
| Irudia handiago ikusteko klik egin bere gainean |
Aurreko 7a-ZenbakiAleatorioak.cbp programaren bigarren for aginduan iZbk zenbaki aleatoriotik abiatuta 17 eta 21 arteko iZbkEskalatua zenbaki aleatorioa lortzen den, eta iZbk zenbaki aleatoriotik abiatuta 14.55 eta 19.66 esparruko fZbk zenbaki aleatorioa lortzen da.
Jakina denez, rand() funtzioak itzultzen duen ausazko zenbakia algoritmo baten bidez sortzen da. Algoritmo horrek erlazionatu gabeko zenbaki batzuk ematen ditu; horretarako, abiapuntu edo hazi gisa 1 balioa hartzen da. Hori dela eta, zenbaki aleatorioen segida berdinak emango ditu rand() funtzioak programaren exekuzio guztietan. Arazo hau konpontzeko, srand() funtzioa erabiliko dugu.
Zenbaki aleatorioen sorgailua martxan jartzeko srand() funtzio erabil daiteke. Sortuko den zenbakien sekuentzia desberdina bermatzeko, ohikoa da parametrotzat uneko denbora erabiltzea time(NULL) funtzio-deia eginez (kontutan izan time() funtzioak time.h liburutegia behar duela). Bestalde, srand() funtzioak int sarrerako parametroa behar du baina ez du ezer itzultzen.
Ondoko programa honetan ere zortzi zenbaki aleatorio lortzen dira birritan. Baina, oraingoan srand() funtzioari esker, exekuzio bakoitzeko, zenbaki aleatorio desberdinak lortuko dira:
/* 7b-ZenbakiAleatorioak: rand() eta srand() funtzioak */
// 8 zenbaki oso sortu eta pantailaratu eskalatu gabe eta eskalatuta: [0, 5] eta [0.0, 0.99]
// 8 zenbaki oso sortu eta pantailaratu eskalatu gabe eta eskalatuta: [17, 21] eta [14.55, 19.66]
#include <stdio.h>
#include <stdlib.h> // rand() funtziorako eta RAND_MAX makrorako
#include <time.h> // time() funtzioarako
#define iMIN 17 // behemuga
#define iMAX 21 // goimuga
#define fMIN 14.55 // behemuga
#define fMAX 19.66 // goimuga
int main()
{
int iKont;
int iZbk, iZbkEskalatua;
float fZbk;
printf("\nRAND_MAX = %d\n", RAND_MAX);
srand(time(NULL)); // gaur egungo denboraren araberako hazia ezarri
printf("\n iKont iZbk [0, 5] [0.0, 0.99]");
printf("\n ----- ---- ------ -----------");
...
printf("\n");
return 0;
}
![]() |
| Irudia handiago ikusteko klik egin bere gainean |
Aurreko 7b-ZenbakiAleatorioak.cbp programaren bigarren for aginduan iZbk zenbaki aleatoriotik abiatuta 17 eta 21 arteko iZbkEskalatua zenbaki aleatorioa lortzen den, eta iZbk zenbaki aleatoriotik abiatuta 14.55 eta 19.66 esparruko fZbk zenbaki aleatorioa lortzen da. Baina, oraingoan, programaren exekuzio bakoitzeko zenbaki desberdinak lortuko dira.
Goian ikusi da srand() eta rand() funtzioei esker zenbaki errealak lor daitezkeela, baina hamarteren kopurua ezin da kontrolatu. Horregatik, adibidez 2 hamartarreko zenbaki erreal aleatorioak behar badira honela egingo dugu.
Demagun azterketa baten notak auzaz lortu nahi direla, jakinik kalifikaziorik txikiena 0.00 dela eta kalifikaziorik handiena 9.99 dela. Beraz, edozein notarako:
- unitatea 0 eta 9 artekoa,
- hamarrekoa 0 eta 9 artekoa eta
- ehunekoa 0 eta 9 artekoa.
Nahiz eta notak zenbaki errealak diren, balio aleatorioak lortzean 0 eta 9 arteko kopuru osoak erabiliko ditugu:
/* Ariketa-19b3_FuntzioEstandarrak: zenbaki sasi-aleatorioak lortzen (kopuru errealak) */
// rand() ikasiko dugu, baina srand() funtzioarekin lotuta dago.
// Zenbaki aleatorioen segida lortzeko hazi bat behar da eta time() funtzioa erabiliko da
// NULL parametroarekin zeinek igarotako segundoak itzultzen ditu 1970-01-01 datatik hasita.
// rand() bitartez lortuko diren zenbaki aleatorioak 0 eta RAND_MAX=32767 arteko kopuru
// osoak izango dira. Hamartar bakarra duen zenbaki erreala lortzeko osoekin lan egin daiteke.
// Demagun azterketa baten nota adierazten duten 0.00 eta 9.99 arteko hainbat zenbaki erreal
// ditugula eta nota guztien batezbesteko aritmetikoa kalkulatu nahi dela.
#include <stdio.h> // printf() funtzioarako
#include <stdlib.h> // rand() eta srand() funtzioetarako
#include <time.h> // time() funtzioarako
#define iZENBAT 20
int main()
{
float fNota;
int iUnitatea;
int iHamarrekoa;
int iEhunekoa;
float fBatukaria = 0.0;
srand(time(NULL)); // srand() zenbaki aleatorioak berriro hasiarazteko, hazia behar du
// Hazia, adibidez, time(NULL) funtzioa izan daiteke zeinek igarotako
// segundoak itzultzen dituen 1970-01-01 datatik hasita
printf("\n");
printf(" %d kalifikazio: 0.00 eta 9.99 arteko balio sasi-aleatorioak\n", iZENBAT);
printf(" -----------------------------------------------------------\n");
for (int iKont = 1; iKont <= iZENBAT; iKont++)
{
iUnitatea = rand() % 10; // 0 eta 9 arteko balioak
iHamarrekoa = rand() % 10; // 0 eta 9 arteko balioak
iEhunekoa = rand() % 10; // 0 eta 9 arteko balioak
fNota = iUnitatea + 0.1*iHamarrekoa + 0.01*iEhunekoa;
fBatukaria = fBatukaria + fNota;
printf("%4d iUnitatea=%d iHamarrekoa=%d iEhunekoa=%d fNota=%.2f\n", iKont, iUnitatea, iHamarrekoa, iEhunekoa, fNota);
}
printf(" -----------------------------------------------------------\n");
printf("\n Bataztesteko aritmetikoa %.2f da\n", fBatukaria/iZENBAT);
printf("\n");
return 0;
}
Dakigunez rand() funtzioak osoa den zenbaki bat itzultzen du eta bere esparrua 0 eta RAND_MAX artean dago. Baina esparrua itxia ala irekia da? Hau da, esparruaren mugak diren 0 eta RAND_MAX=32767 balioak itzultzen ditu rand() funtzioak?
Erantzuna baietz da eta hurrengo programan erakusten den bezala, rand() funtzioak itzultzen duenaren emaitza esparru itxi honetan aurkituko da [0, 32767] muga biak barne.
Programa honek zenbaki aleatorioz betetzen du aiZenbakiak izeneko arraya eta array horren 8000 elementuetan bilatzen da 0 datua dagoen eta 32767 datua dagoen, bietariko bateren falta bada (ala biak falta badira) berriro errepikatzen da beste 8000 elementuekin aiZenbakiak arraya elikatzea:
/* 7d-ZenbakiAleatorioak.cbp: rand() funtzioaren mugak neurtzen */
// rand() funtzioak zenbaki sasi-aleatorio bat itzultzen du 0 eta RAND_MAX
// balioen artean biak barne, hau da [0, 32676] arteko esparruko emaitza.
#include <stdio.h> // printf() funtzioarako
#include <stdlib.h> // rand() eta srand() funtzioetarako
#include <time.h> // time() funtzioarako
#include <ctype.h> // toupper() funtziorako
#define MAXIMOA 8000 // arraya beti dago beterik, LuzeraFisikoa==LuzeraLogikoa
void ArrayaBete(int[]); // bigarren parametroa falta da arraya beterik dagoelako
int iBilatu(const int[], int); // bigarren parametroa falta da arraya beterik dagoelako
void ArrayaErakutsi(const int[], int, int);
int main()
{
int aiZenbakiak[MAXIMOA];
int iSaiakera;
int iPosizio_ZERO;
int iPosizio_RANDMAX;
char cErantzuna;
printf("\n rand() >>> [0, %d] biak barne\n", RAND_MAX);
srand(time(NULL)); // Gaur egungo denboraren araberako hazia ezarri. Hazia,
// adibidez, time(NULL) funtzioa izan daiteke zeinek igarotako
// segundoen kopurua itzultzen du 1970-01-01 datatik hasita.
printf("\nSaiakera 0 non dago 32676 non dago");
printf("\n======== ==================== =======================");
iSaiakera = 0;
do
{
ArrayaBete(aiZenbakiak); // MAXIMOA bigarren parametroaren ordez
iPosizio_ZERO = iBilatu(aiZenbakiak, 0);
iPosizio_RANDMAX = iBilatu(aiZenbakiak, RAND_MAX);
iSaiakera++;
printf("\n %4d iPosizio_ZERO = %4d iPosizio_RANDMAX = %4d", iSaiakera, iPosizio_ZERO, iPosizio_RANDMAX);
} while (iPosizio_ZERO == -1 || iPosizio_RANDMAX == -1);
printf("\n======== ==================== =======================");
printf("\n%d elementuko arrayan 0 eta 32676 balioen posizioak goian", MAXIMOA);
printf("\n\n");
do
{
printf("\a Arrayaren zati hori pantailaratuko da? (B/E): ");
scanf("%c", &cErantzuna);
fflush(stdin);
cErantzuna = toupper(cErantzuna);
} while (cErantzuna != 'E' && cErantzuna != 'B');
if (cErantzuna == 'B')
{
if (iPosizio_ZERO > iPosizio_RANDMAX)
ArrayaErakutsi(aiZenbakiak, iPosizio_RANDMAX, iPosizio_ZERO);
if (iPosizio_RANDMAX > iPosizio_ZERO)
ArrayaErakutsi(aiZenbakiak, iPosizio_ZERO, iPosizio_RANDMAX);
}
printf("\n\n 0 balioko elementuaren lehen agerpena arrayaren ");
printf("%d. posizioan ematen da.", iPosizio_ZERO);
printf("\n%d balioko elementuaren lehen agerpena arrayaren ", RAND_MAX);
printf("%d. posizioan ematen da.\n", iPosizio_RANDMAX);
printf("\n rand() >>> [0, %d] biak barne\n\n", RAND_MAX);
return 0;
}
// Luzera efektiboa den bigarren parametroaren ordez: MAXIMOA
void ArrayaBete(int iZenbakiak[])
{
int iKont;
for (iKont=0; iKont<MAXIMOA; iKont++)
iZenbakiak[iKont] = rand(); // zenbaki aleatorioa sortu eta gorde
}
void ArrayaErakutsi(const int iZenbakiak[], int iPosLehena, int iPosBigarrena)
{
int iKont;
for (iKont=0; iKont<=iPosBigarrena; iKont++)
{
if (iKont <= iPosLehena)
{
if (iKont == iPosLehena)
printf("\n---------------------------------------------------------------------------");
printf("\n \t iZenbakiak[%5d] = %5d \t iZenbakiak[%5d] = %5d", iKont, iZenbakiak[iKont], iKont, iZenbakiak[iKont]);
}
else
printf("\n \t iZenbakiak[%5d] = %5d \t iZenbakiak[%5d] = %5d", iKont, iZenbakiak[iKont], iPosLehena, iZenbakiak[iPosLehena]);
}
}
// Luzera efektiboa den bigarren parametroaren ordez: MAXIMOA
int iBilatu(const int aiZenbakiak[], int iDatua)
{
int iKont = -1; // -1 gezurrezko posizioa litzateke, ikusi BEHEMUGA = 0 dela
do
{
iKont++;
} while ((aiZenbakiak[iKont] != iDatua) && (iKont < MAXIMOA));
// emaitza itzultzeko if-else baldintzazko agindua erabiltzen da:
// gakoa den zenbaki osoa aurkitzean bere iKont indizea itzuli,
// ez bada gako hori aurkitzen -1 gezurrezko posizioa itzuli.
if (aiZenbakiak[iKont] == iDatua)
return iKont; // aurkitzen bada dagokion indizea itzuli
else
return -1; // ez bada aurkitzen -1 gezurrezko posizioa itzuli
}
|


iruzkinik ez:
Argitaratu iruzkina