2025(e)ko otsailaren 25(a), asteartea

Ariketa 43 | Menu bat azpiprogramaz (char)

ZER DAKIDAN:
switch baldintzazko egitura ikasi nuen aukera anitzak antolatzeko (Ariketa 18 | Aukera anitzen arteko hautapena adibidea eta Ariketa 36 | Hainbat aukeren menu bat adibidea gogoratzen ditut).



ZER IKASIKO DUDAN:
Menu bat programatuko dut funtzioak erabiliz, erabiltzaileak gogoko duen hautapena cAukeraHautatu() funtzioan irakurtzen den karaktere bat izango da.







Bost aukera dituen menu batek gidatuko du programa. Aukerak hautatzeko karaktereak erabiltzen dira eta bostetatik aukera batek programa bukarazten du. Hautatutako aukerari esker switch agindu baten bitartez gidatzen da programaren exekuzioa (Ariketa 18 | Aukera anitzen arteko hautapena gogoratu). Menua pantailan aurkezteko lana eta erabiltzailearen aukeraren bat hautatzeko lana cAukeraHautatu() izeneko funtzioak egiten du:


Lehenik idatzi behar dugun main() funtzio nagusia, funtsean, prozesu errepikakor bat da, errepikapenak eteteko eta programatik irteteko I edo i karakterea sartu behar da. Deskriba ditzagun, banan-banan gainerako lau aukerak, eta ikus dezagun ere programa osoaren kodea.


cAukeraHautatu() funtzioan irakurritako A edo a karakterea main() funtzio nagusira helduko da eta funtzio nagusian DiagonalkiPantailaratu() funtzioak sarreratzat behar duen karakterea irakurriko da (funtzio horrek datu bakar bat behar du, alfabeto larriaren letra bat). Lehen aukera hau amaitzeko, DiagonalkiPantailaratu() funtzioak jarraian erakusten den mezua emateko gai da:




cAukeraHautatu() funtzioan irakurritako B edo b karakterea main() funtzio nagusira helduko da eta funtzio nagusian TaulaPantailaratu() funtzioak sarreratzat behar duen zenbaki osoa irakurriko da (funtzio horrek datu bakar bat behar du, 0 eta 9 arteko zenbaki osoa). Bigarren aukera hau bukatzeko, TaulaPantailaratu() funtzioak jarraian erakusten den mezua emateko gai da:




cAukeraHautatu() funtzioan irakurritako C edo c karakterea main() funtzio nagusira helduko da eta funtzio nagusian dbErroKuboaKalkulatu() funtzioaren sarrera den zenbaki erreala irakurriko da (funtzio horrek datu bakar bat behar du, zenbaki erreala eta positiboa). dbErroKuboaKalkulatu() funtzioaren deia egin ondoren, main() funtzio nagusian jarraian erakusten den mezuaren bezalakoak agertuko dira:




cAukeraHautatu() funtzioan irakurritako D edo d karakterea main() funtzio nagusira helduko da eta funtzio nagusian boFibonaccikoaDa() funtzioaren sarrera den zenbaki osoa irakurriko da (funtzio horrek datu bakar bat behar du, 3 eta 17000 arteko zenbaki osoa). boFibonaccikoaDa() funtzioaren deia egin ondoren, main() funtzio nagusiari balio boolear itzuliko dio eta balio boolear (FALSE ala TRUE) eta horren arabera programak honelako mezuak erakutsiko ditu:






Hona hemen Ariketa-43b_MenuaAzpiprogramaz.cbp proiektuaren iturburu-programa:
/* Ariketa-43b_MenuaAzpiprogramaz: menuaren aukeratzailea char datu-motakoa */

#include <stdio.h>
#include <stdlib.h>    // system() funtziorako
#include <conio.h>     // getche() funtziorako
#include <ctype.h>     // toupper() funtziorako
#include <math.h>      // fabs() funtziorako


char cAukeraHautatu(void);
void DiagonalkiPantailaratu(char);
void TaulaPantailaratu(int);
double dbErroKuboaKalkulatu(double);
int iFibonaccikoaDa(int);


int main()
{
    char cAukera, cLetra;
    int iZbk;
    double dbZbk, dbKuboa;

    do
    {
        system("cls");  // pantaila garbitu
        cAukera = cAukeraHautatu();

        printf("\n\n");
        switch (cAukera)
        {
            case 'A':
                do
                {
                    printf("A eta Z arteko letra bat eman: ");
                    scanf("%c", &cLetra);
                    cLetra = toupper(cLetra);
                } while (cLetra < 'A' || cLetra > 'Z');
                DiagonalkiPantailaratu(cLetra);
                break;
            case 'B':
                do
                {
                    printf("0 eta 9 arteko zenbaki osoa eman: ");
                    scanf("%d", &iZbk);

                } while (iZbk < 0 || iZbk > 9);
                TaulaPantailaratu(iZbk);
                break;
            case 'C':
                do
                {
                    printf("Zenbaki erreala eta positiboa eman: ");
                    scanf("%lf", &dbZbk);
                } while (dbZbk < 0.0);
                dbKuboa = dbErroKuboaKalkulatu(dbZbk);
                printf("%0.5f-ren erro kuboa: %0.5f\n\n", dbZbk, dbKuboa);
                break;
            case 'D':
                do
                {
                    printf("3 eta 6000 arteko zenbaki osoa eman: ");
                    scanf("%d", &iZbk);
                } while (iZbk < 3 || iZbk > 6000);
                if (iFibonaccikoaDa(iZbk) == 0)
                    printf("Ez, %d ez da Fibonacciren sekuentziakoa\n\n", iZbk);
                else
                    printf("Bai, %d Fibonacciren sekuentziakoa da\n\n", iZbk);
                break;
            case 'I':
                printf("\nPrograma amaitzera doa...\n");
                break;
        }

        // getchar();   // soberan 79 lerrokoa getche() bada 
                        // derrigorrezkoa 79 lerrokoa getchar() bada
        if (cAukera != 'I')
        {
            printf("Emaitzak ikusi ahal izateko itxaroten... ");
            getche();  // itxaroteko
        }
    } while (cAukera != 'I');

    return 0;
}


char cAukeraHautatu()
{
    char cHautapena;

    printf("==========================Menua==========================\n");
    printf("  A   Alfabeto zatia diagonalki\n");
    printf("  B   Biderkatzeko taula marraztu\n");
    printf("  C   Zenbaki baten erro kuboa Newton-Raphson bitartez\n");
    printf("  D   Zenbaki bat Fibonacciren sekuentziakoa da?\n");
    printf("\n");
    printf("  I   Programatik irten\n");
    printf("=========================================================\n");
    printf("                                Zure aukera: ");

    do
    {
        cHautapena = getche();
        cHautapena = toupper(cHautapena);

        if ((cHautapena < 'A' || cHautapena > 'D') && cHautapena != 'I')
        {
            printf("\n\aAukera ez da ondo hautatu. Berriro aukeratu: ");
        }
    } while ((cHautapena < 'A' || cHautapena > 'D') && cHautapena != 'I');

    return cHautapena;
}


void DiagonalkiPantailaratu(char cLetra)
{
    printf("Alfabeto zatia diagonalki pantailaratu:\n");

    int iNon = 15;
    for (char k = 'A'; k <= cLetra; k++)
    {
        printf("%*c\n", iNon, k);
        iNon++;
    }
    printf("\n");
}


void TaulaPantailaratu(int iZbk)
{
    printf("%d zenbakiaren biderkatzeko taula:\n", iZbk);
    for (int k = 1; k <= 10; k++)
    {
        printf("%35d x %d = %2d\n", k, iZbk, k * iZbk);
    }
    printf("\n");
}


double dbErroKuboaKalkulatu(double dbZbk)
{
    const double fEpsilon = 0.000000001;
    double dbKuboa = dbZbk / 3.0; // Lehendabiziko hurbilketa
    double dbAurrekoa;

    do
    {
        dbAurrekoa = dbKuboa;
        dbKuboa = (dbZbk / (dbAurrekoa * dbAurrekoa) + 2 * dbAurrekoa) / 3;
        dbKuboa = dbAurrekoa - (dbAurrekoa * dbAurrekoa * dbAurrekoa - dbZbk) / (3 * dbAurrekoa * dbAurrekoa);
    } while (fabs(dbKuboa - dbAurrekoa) > fEpsilon);

    return dbKuboa;
}


int iFibonaccikoaDa(int iZbk)
{
    int iFibo1 = 0, iFibo2 = 1, iFibo3 = iFibo1 + iFibo2;

    while (iFibo3 < iZbk)
    {
        iFibo1 = iFibo2;
        iFibo2 = iFibo3;
        iFibo3 = iFibo1 + iFibo2;
        printf("\tiFibo3 = %4d \t\t (%4d == %d) = %d\n", iFibo3, iFibo3, iZbk, iFibo3 == iZbk);
    }
    // C lengoaian zero gezurra da eta, ondorioz, zero ez dena egia da
    return (iFibo3 == iZbk);
}





Gure programak egiterakoan, ondoko lau gomendio hauek jarraitu:

  1. Programaren exekuzioa geldiarazteko, hots, pantaila jakin batean itxaroteko getche() funtzioa aplikatu. Beraz, getchar() ez egin ezta getch().
  2. Karaktereak teklatuz irakurtzeko betiko scanf() funtzioa erabili. Beraz, getchar() ez egin ezta getche() edo getch().
  3. Karaktereak pantailan idazteko betiko printf() funtzioa erabili. Beraz, putchar() ez egin.
  4. Bufferra beti garbitu. Horretarako, scanf() guztien ostean fflush(stdin) egin.

Lau gomendio horiek kontutan izanik, goiko Ariketa-43b_MenuaAzpiprogramaz.cbp proiektua honelaxe geratzen da: Ariketa-43c_MenuaAzpiprogramaz.cbp proiektua.

 

Ariketa 43 | Menu bat azpiprogramaz (int)

ZER DAKIDAN:
switch baldintzazko egitura ikasi nuen aukera anitzak antolatzeko (Ariketa 18 | Aukera anitzen arteko hautapena adibidea eta Ariketa 36 | Hainbat aukeren menu bat adibidea gogoratzen ditut).



ZER IKASIKO DUDAN:
Menu bat programatuko dut funtzioak erabiliz, erabiltzaileak gogoko duen hautapena iAukeraHautatu() funtzioan irakurtzen den karaktere bat izango da.







Lau aukera dituen menu batek gidatuko du programa. Aukerak hautatzeko zenbaki osoak erabiltzen dira eta lau aukeretatik batek programa bukarazten du. Hautatutako aukerari esker switch agindu baten bitartez programaren exekuzioa gidatzen da (Ariketa 18 | Aukera anitzen arteko hautapena gogoratu). Menua pantailan aurkezteko lana eta erabiltzailearen aukeraren bat hautatzeko lana iAukeraHautatu() izeneko funtzioak egiten du:

iAukeraHautatu() funtzioaren lana: Menua aurkeztu eta aukera hautatu

Lehenik idatzi behar dugun main() funtzio nagusia, funtsean, prozesu errepikakor bat da, errepikapenak eteteko eta programatik irteteko 0 balioa sartu behar da. Deskriba ditzagun, banan-banan gainerako hiru aukerak, eta ikus dezagun ere programa osoaren kodea.


iAukeraHautatu() funtzioan irakurritako 1 balioa main() funtzio nagusira helduko da eta funtzio nagusian DiagonalkiPantailaratu() funtzioak sarreratzat behar duen zenbaki osoa irakurriko da (funtzio horrek datu bakar bat behar du, 3 eta 17000 arteko zenbaki oso bat). Lehen aukera hau amaitzeko, DiagonalkiPantailaratu() funtzioak jarraian erakusten den mezua emateko gai da:

Laranjaz main() funtziokoa eta urdinez iFibonaccikoaDa() funtziokoa



iAukeraHautatu() funtzioan irakurritako 2 balioa main() funtzio nagusira helduko da, ondoren, dbErroKuboaKalkulatu() funtzioak sarreratzat behar duen zenbaki erreala irakurriko da main() funtzio nagusian eta bere kuboaren balioa erakutsiko da ere. Emaitza lortzen duen dbErroKuboaKalkulatu() funtzioak pantailan erakusten duena urdinez markatu da jarraian erakusten den irudian:

Laranjaz main() funtziokoa eta urdinez fKosinuaKalkulatu() funtziokoa



iAukeraHautatu() funtzioan irakurritako 3 balioa main() funtzio nagusira helduko da, ondoren, fKosinuaKalkulatu() funtzioak sarreratzat behar duen zenbaki erreala irakurriko da main() funtzio nagusian eta bere kuboaren balioa erakutsiko da ere. Emaitza lortzen duen fKosinuaKalkulatu() funtzioak pantailan erakusten duena urdinez markatu da jarraian erakusten den irudian:

Laranjaz main() funtziokoa eta urdinez dbErroKuboaKalkulatu() funtziokoa





Hona hemen Ariketa-43a_MenuaAzpiprogramaz.cbp proiektuaren iturburu-programa:
/* Ariketa-43a_MenuaAzpiprogramaz: menuaren aukeratzailea int datu-motakoa */

#include <stdio.h>
#include <stdlib.h>     // system() funtziorako
#include <math.h>

#define EPSILON_1 0.0005     // bost hamarmilaren
#define EPSILON_2 0.0000001  // miloiaren bat

int iAukeraHautatu(void);
double dbErroKuboaKalkulatu(double);
int iFibonaccikoaDa(int);
float fBerreketa(float fOinarria, int iAldiak);
long liFaktoriala(int iMuga);
float fKosinuaKalkulatu(float fX);


int main()
{
    int iAukera;
    int iZbk;
    double dbZbk, dbKuboa;
    float fAng, fX, fKosinua;

    do
    {
        system("cls");  // pantaila garbitu
        iAukera = iAukeraHautatu();

        printf("\n");
        switch (iAukera)
        {
            case 1:
                do
                {
                    printf("3 eta 17000 arteko zenbaki osoa eman: ");
                    scanf("%d", &iZbk);
                } while (iZbk < 3 || iZbk > 17000);
                if (iFibonaccikoaDa(iZbk) == 1)
                    printf("%d Fibonacciren sekuentziakoa da\n\n", iZbk);
                else
                    printf("%d ez da Fibonacciren sekuentziakoa\n\n", iZbk);
                break;
            case 2:
                do
                {
                    printf("Zenbaki erreala eta positiboa eman: ");
                    scanf("%lf", &dbZbk);
                } while (dbZbk < 0.0);
                dbKuboa = dbErroKuboaKalkulatu(dbZbk);
                printf("%0.5f-ren erro kuboa: %0.5f\n\n", dbZbk, dbKuboa);
                break;
            case 3:
                printf("1. koadranteko angelu baten kosinua kalkulatu %.4f prezisioarekin\n\n", EPSILON_1);

                do
                {
                    printf("1. koadranteko angelua graduetan: ");
                    scanf("%f", &fAng);
                } while (fAng < 0.0 || fAng >= 90.0);

                fX = fAng * 2 * M_PI / 360; // graduak radianetara bihurtu
                printf("Angelua radianetan: %8.5f\n", fX);

                fKosinua = fKosinuaKalkulatu(fX);

                printf("\n");
                printf("Gure programaz lortutako kosinua[%.3f gradu] -----> %7.5f\n", fAng, fKosinua);
                printf("cos() funtzioak ematen duena cos(%.3f gradu) -----> %7.5f\n", fAng, cos(fX));
                printf("\n");
                break;
            case 0:
                printf("Programa amaitzera doa. Edozein tekla sakatu.\n");
                break;
        }

        getchar(); // bufferrean jarritako return karakterea hartzen du
        if (iAukera != 0)
        {
            printf("Emaitzak ikusi ahal izateko itxaroten, aurrera egiteko INTRO sakatu... ");
            getchar();  // itxaroteko
        }
    } while (iAukera != 0);

    return 0;
}


int iAukeraHautatu()
{
    int iHautapena;

    printf("============================Menua=============================\n");
    printf("  1   Zenbaki bat Fibonacci-ren sekuentziakoa da\n");
    printf("  2   Zenbaki baten erro kuboa Newton-Raphson bitartez\n");
    printf("  3   Lehen koadranteko angelu baten kosinua Taylor bitartez\n");
    printf("\n");
    printf("  0   Programatik irten\n");
    printf("==============================================================\n");
    printf("                                Zure aukera: ");

    do
    {
        scanf("%d", &iHautapena);
        if (iHautapena < 0 || iHautapena > 3)
        {
            printf("Aukera ez da ondo hautatu. Berriro aukeratu: ");
        }
    } while (iHautapena < 0 || iHautapena > 3);

    return iHautapena;
}


void DiagonalkiPantailaratu(char cLetra)
{
    printf("Alfabeto zatia diagonalki pantailaratu:\n");

    int iNon = 15;
    for (char k = 'A'; k <= cLetra; k++)
    {
        printf("%*c\n", iNon, k);
        iNon++;
    }
    printf("\n");
}


void TaulaPantailaratu(int iZbk)
{
    printf("%d zenbakiaren biderkatzeko taula:\n", iZbk);
    for (int k = 1; k <= 10; k++)
    {
        printf("%35d x %d = %2d\n", k, iZbk, k * iZbk);
    }
    printf("\n");
}


double dbErroKuboaKalkulatu(double dbZbk)
{
    double dbKuboa = dbZbk / 3.0; // Lehendabiziko hurbilketa
    double dbAurrekoa;
    int iIterazioa = 1;

    do
    {
        dbAurrekoa = dbKuboa;
        dbKuboa = (dbZbk / (dbAurrekoa * dbAurrekoa) + 2 * dbAurrekoa) / 3;
        dbKuboa = dbAurrekoa - (dbAurrekoa * dbAurrekoa * dbAurrekoa - dbZbk) / (3 * dbAurrekoa * dbAurrekoa);
        printf("%d. iterazioan...   kuboa = %.9lf  eta  errorea = %.9lf\n", iIterazioa, dbKuboa, fabs(dbKuboa - dbAurrekoa));
        iIterazioa++;
    } while (fabs(dbKuboa - dbAurrekoa) > EPSILON_2);

    return dbKuboa;
}


int iFibonaccikoaDa(int iZbk)
{
    int iFibo1 = 0;
    int iFibo2 = 1;
    int iFibo3 = iFibo1 + iFibo2;

    while (iFibo3 < iZbk)
    {
        iFibo1 = iFibo2;
        iFibo2 = iFibo3;
        iFibo3 = iFibo1 + iFibo2;
        printf("iFibo3 = %8d\n", iFibo3);
    }

    if (iFibo3 == iZbk)
        return 1;
    else
        return 0;
}


float fBerreketa(float fOinarria, int iAldiak)
{
    float fMetagailua = 1.0;
    int i;

    for (i = 0; i < iAldiak; i++)
    {
        fMetagailua *= fOinarria;
    }
    return fMetagailua;
}


long liFaktoriala(int iMuga)
{
    long liMetagailua = 1;
    int i;

    for (i = 1; i <= iMuga; i++)
    {
        liMetagailua *= i;
    }
    return liMetagailua;
}


float fKosinuaKalkulatu(float fX)
{
    int iKont = 0;
    float fKosinua = 0.0;
    float rBatugai = 1.0;
    long int liFaktoreak;
    float fBerredura;
    float fZeinua;

    while (fabs(rBatugai) > EPSILON_1)
    {
        fKosinua += rBatugai;
        iKont += 2;

        liFaktoreak = liFaktoriala(iKont);
        fBerredura = fBerreketa(fX, iKont);
        fZeinua = fBerreketa(-1, iKont / 2);

        rBatugai = fZeinua * fBerredura / liFaktoreak;
        printf("%d. iterazioan ==>  kosinua: %8.5f | batugaia: %8.5f | aldea: %8.5f\n", iKont/2, fKosinua, rBatugai, fabs(fabs(rBatugai) - EPSILON_1));
    }
    return fKosinua;
}
 
 

2025(e)ko otsailaren 24(a), astelehena

Ariketa 42 | Taylor azpiprogramaz (edozein angelurako)

ZER DAKIDAN:
Taylor algoritmoa aplikatuz kosinua eta sinua kalkulatzeko gai naiz, sarrerako angelua txikia denean.


ZER IKASIKO DUDAN:
Taylor algoritmoa aplikatuz kosinua eta sinua kalkulatzen ikasiko dut, sarrerako angelua edozein delarik.






Ariketa 41 | Taylor azpiprogramaz (angelu txikietarako) blog-artikuluan ikusi dugu Taylor metodoa nola aplikatzen zaion 0 eta Π/2 artean dagoen sarrerako x angelu bati. Baina eta edozein angelu sartuko bagenu? Ikusitako programak ondo ibiliko lirateke? Kalkulu ahulena zein izan daiteke?

Ariketa 41 | Taylor azpiprogramaz (angelu txikietarako) artikuluko programa aldatzen baduzu sarrerako datua 0.0 gradu eta 360.0 gradu artekoa izan dadin; ikusiko duzu nola 160 graduko angelu batekin ondo dabilela, baina 160.9 graduko angeluarekin programa ez dabilela ikusi dugu ere. Arazoa faktorialaren kalkulu honetan dago:
// faktoriala kalkulatzeko funtzioa, emaitza long in
long int liFaktoriala(int iMuga)
{
    long int liMetagailua = 1;
    int i;

    for (i = 1; i <= iMuga; i++)
    {
        liMetagailua *= i;
    }
    return liMetagailua;
}
Faktorialaren kalkulua ondo dago. Baina iMuga datua handia bada, gerta daiteke liMetatua handiegia izatea longint datu-motarako eta orduan funtzioaren emaitza desegokia izango litzateke.

Izan ere, goiko funtzio horretan, faktoriala lortzean emaitza longint datu-motako aldagai batean gordetzen da, eta angelu handiekin faktorialaren balioak longint datu-motak duen muga gainditzen du. Horregatik, 0.0 gradu eta 360.0 gradu arteko angeluekin lan egin ahal izateko, faktorialaren funtzioa aldatuko dugu bere emaitza float datu-motakoa edo double datu-motakoa izan dadin.
// faktoriala kalkulatzeko funtzioa, emaitza double
double dbFaktoriala(int iMuga)
{
    double dbMetagailua = 1.0;
    int i;

    for (i = 1; i <= iMuga; i++)
    {
        dbMetagailua *= i;
    }
    return dbMetagailua;
}

Sarrerako angelua oso handia bada, esate baterako 98765.9 graduko angelua sartuko bagenu, hurrengo moldaketa aplikatuko genioke:
Datua den 98765.9 gradu zati 360 egin ondoren, 98765.9/360 eta zatiketaren hondarrarekin geratuko ginateke bere kosinua kalkulatzeko. Zatiketa horren zatidurak adierazten du 98765.9 graduko angeluak zirkuluari zenbat bira ematen dizkion eta kosinuaren kalkulurako garrantzirik ez du. Ez-osoa den zenbaki baten atalak nola lortzen diren gogoratu:

dbHondarra = fmod(dbZatikizuna, dbZatitzailea);   // edo...

iGraduak = (int)fDatuaGradutan;         // kopuru osoa lortu
fHondarra = fDatuaGradutan - iGraduak;  // hamartarrak lortu




Doikuntza konstante bat izanik, Taylor serie bidezko hurbilpena dela eta, hauxe izan daiteke edozein angelurako kosinua kalkulatzen duen programa non AngeluaEgokitu() funtzioa balio erantsia da:
/* Ariketa-42_TaylorKosinua-EdozeinAngelu: kosinua Taylor bitartez. */

// Edozein angelu positibo teklatuz eman eta dagokion
// kosinua kalkulatuko da Taylor segida jarraituz.

// Erabilitako funtzioak eta itzulitako datu-mota:
//   liFaktoriala() --------> long int
//   fBerreketa() ----------> float
//   fKosinuaKalkulatu() ---> float
//   AngeluaEgokitu() ------> void (bi emaitzak parametroen bidez)

#include <stdio.h>
#include <math.h>    // M_PI konstanterako

#define EPSILON 0.0005  // bost hamarmilaren

long int liFaktoriala(int iMuga);
float fBerreketa(float fOinarria, int iAldiak);
float fKosinuaKalkulatu(float fX);
void AngeluaEgokitu(float fAng, float *fAngEgokitua, int *iKoadrantea);


int main()
{
    float fAng, fAngRadianetan, fX, fKosinua;
    int iKoadrantea;

    printf("Edozein angelu positiboaren kosinua kalkulatu %.4f prezisioarekin\n\n", rEPSILON);
    do
    {
        printf("Edozein angelu graduetan (adibidez, 1234 gradu): ");
        scanf("%f", &fAng);
    } while (fAng < 0.0);

    AngeluaEgokitu(fAng, &fX, &iKoadrantea);

    fAngRadianetan = fAng * 2 * M_PI / 360;
    fX = fX * 2 * M_PI / 360;
    printf("Angelua radianetan: %.5f\n", fX);

    fKosinua = fKosinuaKalkulatu(fX);

    if (iKoadrantea == 2 || iKoadrantea == 3)
        fKosinua = -fKosinua;

    printf("\nGure programaz lortutako kosinua[%.3f gradu] -----> %.5f\n", fAng, fKosinua);
    printf("cos() funtzioak ematen duena cos(%.3f gradu) -----> %.5f\n", fAng, cos(fAngRadianetan));

    printf("\nRETURN tekla sakatu programatik irteteko\n");
    getchar(); getchar();
    return 0;
}


// berredura kalkulatzeko funtzioa
float fBerreketa(float fOinarria, int iAldiak)
{
    float fMetagailua = 1.0;
    int i;

    for (i = 0; i < iAldiak; i++)
    {
        fMetagailua *= fOinarria;
    }
    return fMetagailua;
}


// faktoriala kalkulatzeko funtzioa
long int liFaktoriala(int iMuga)
{
    long int liMetagailua = 1;
    int i;

    for (i = 1; i <= iMuga; i++)
    {
        liMetagailua *= i;
    }
    return liMetagailua;
}


// Taylor seriea erabiliz kosinua kalkulatzeko funtzioa
float fKosinuaKalkulatu(float fX)
{
    long int liFaktoreak;
    float fBerredura;
    float fZeinua;
    int iKont = 0;
    float fKosinua = 0.0;
    float fBatugai = 1.0;

    printf("\n%34s %20s %15s", "Faktoriala", "Berredura", "Batugaia");
    printf("\n%34s %20s %15s", "----------", "---------", "--------");
    printf("\n");
    while (fabs(fBatugai) > rEPSILON)
    {
        fKosinua += fBatugai;
        iKont += 2;

        liFaktoreak = liFaktoriala(iKont);
        fBerredura = fBerreketa(fX, iKont);
        fZeinua = fBerreketa(-1, iKont / 2);

        fBatugai = fZeinua * fBerredura / liFaktoreak;
        printf("%2d. iterazioan =====> %12ld %20.5f %15.5f\n", iKont / 2, liFaktoreak, fBerredura, fBatugai);
    }
    return fKosinua;
}


// angelua egokitzeko funtzioa
void AngeluaEgokitu(float fAng, float *fAngEgokitua, int *iKoadrantea)
{
    float fHondar;
    int iBiraKopurua;

    printf("%.3f gradu egokitzen\n", fAng);
    *fAngEgokitua = fAng;
    printf("Sarrerako angelu positiboa = %.3f gradu\n", *fAngEgokitua);
    iBiraKopurua = (int)(*fAngEgokitua / 360);
    printf("Bira osoak    = %d bira\n", iBiraKopurua);
    fHondar = (*fAngEgokitua / 360) - iBiraKopurua;
    printf("Bira-hondarra = %.3f bira\n", fHondar);
    *fAngEgokitua = 360 * fHondar;
    printf("Angelu egokitua  = %.3f gradu\n", *fAngEgokitua);

    if (*fAngEgokitua >= 0 && *fAngEgokitua < 90)
    {
        printf("Angelu efektiboa = %.5f gradu   (1. koadrantea)\n", *fAngEgokitua);
        *iKoadrantea = 1;
    } else if (*fAngEgokitua >= 90 && *fAngEgokitua < 180)
    {
        printf("Angelu efektiboa = %.5f gradu   (2. koadrantea)\n", 180 - *fAngEgokitua);
        *fAngEgokitua = 180 - *fAngEgokitua;
        *iKoadrantea = 2;
    } else if (*fAngEgokitua >= 180 && *fAngEgokitua < 270) {
        printf("Angelu efektiboa = %.5f gradu   (3. koadrantea)\n", *fAngEgokitua - 180);
        *fAngEgokitua = *fAngEgokitua - 180;
        *iKoadrantea = 3;
    } else if (*fAngEgokitua >= 270 && *fAngEgokitua < 360) {
        printf("Angelu efektiboa = %.5f gradu   (4. koadrantea)\n", 360 - *fAngEgokitua);
        *fAngEgokitua = 360 - *fAngEgokitua;
        *iKoadrantea = 4;
    }
}


  • Ariketa-42_TaylorKosinua-EdozeinAngelu.cbp | main.c  


 

Ariketa 41 | Taylor azpiprogramaz (angelu txikietarako)

ZER DAKIDAN:
Agindu errepikakorretan do-while, while eta for ezagutzen ditut. Bestalde, funtzioak programatzen ikasi dut.



ZER IKASIKO DUDAN:
Kosinua eta sinua kalkulatzeko Taylor algoritmoa programatuko dut, lehenik angelu txikiekin lan eginez eta gero lehen bi koadranteko angeluekin lan eginez.


Brook Taylor


Brook Taylor britainiar matematikaria 1685ean jaio eta 1731ean hil zen. Zientziaren arazo asko aztertu zituen eta 1715. urtean idatzi zuen Methodus incrementorum directa et inversa, bere lan garrantzitsuena, non kalkulu diferentziala eta funtzio deribatua definitu zituen. Liburu berean agertu ziren Taylorren seriea, diferentzia finituen bidezko kalkulua, ekuazio diferentzialen soluzio bereziak, zatikako integrazio-metodoa, etab.

Taylor serie bidezko hurbilpena

Taylor seriea funtzio batek x puntuaren inguruan hartzen duen baliora hurbiltzeko erabil daiteke, seriearen batugai zenbait bakarrik erabiltzen direnean; era honetan, errore bat sortzen da, funtzioaren balioarekin bat datorren seriea ez baita modu osotuan garatzen:
(a=0 balioa denean, serieari MacLaurin serie deritzo)

Funtzio esponentzialaren eta logaritmikoaren serieak



Funtzio trigonometrikoen serieak




Non Bs Bernouilliren zenbakiak diren.

Ariketa hau egiteko, ikusitako hauek gogoratu Ariketa 23 | for: Faktorialen batukariak eta Ariketa 24 | for: Potentzien batukariak artikuluetako programak. Klikatu irudi honen gainean eta grafikoki ikusiko duzu Taylor polinomioa kosinu funtzioarentzat:




Angelu baten kosinua Taylor-ren arabera honela kalkula daiteke:
Non x radianetan emaniko angelua den.

Programa bat idatzi kosinua kalkulatuko duena aurreko segidaren N batugai erabiliz. Batugaien N kopurua ez da ezaguna, batugaiak aintzat hartuko dira azken batugaiaren balio absolutua 0.00001 baino txikiagoa izan arte adibidez (doikuntza hori teklatuaren bitartez emango du programaren erabiltzaileak, edo bestela balio konstante bat izan dadila).

Algoritmoa:

  1. Erabiliko den fDoikuntza prezisioa teklatuz irakurri (edo konstante ezagun bat izan dadila)
  2. Lehenego koadranteko fAng angelua graduetan, teklatuz irakurri
  3. Lehenego koadranteko fAng angelua radianetara igaro fX lortuz
  4. fX angeluari dagokion fKos kosinua lortu Taylor bitartez (azken batugaia fDoikuntza baino txikiagoa)
  5. Taylor bitartez lortu den fKos emaitza eta cos(fX) balioa pantailan erakutsi eta bi balioak elkar alderatu


Demagun lehen kasu honetan batukaria kalkulatzen duen azpiprogramak emaitza bakarra itzuli behar duela, kosinua. Hori dela eta, funtzio baten bitartez programatuko dugu. Diogunez, azpiprograma hori funtzio bat izango da bere prototipoa hau delarik:
float fKosinuaKalkulatu(float fX);

Sarrera: fX radianak (teklatuz irakurritako rAngelua graduak radianetara igarota)
Irteera: float, emandako angeluari dagokion kosinua Taylor bitartez

Hauxe izan daiteke lehen bertsioaren programa:

/* Ariketa-41a1_TaylorKosinua_1_koadrantea: kosinua Taylor bitartez. */

// 1. koadranteko angelu bat teklatuz eman eta dagokion kosinua
// kalkulatuko da Taylor segida jarraituz.

// Erabilitako funtzioak eta itzulitako datu-motak:
//   liFaktoriala() --------> long int
//   fBerreketa() ----------> float
//   fKosinuaKalkulatu() ---> float

#include <stdio.h>
#include <math.h>    // M_PI konstanterako

#define EPSILON 0.0005  // bost hamarmilaren

float fBerreketa(float fOinarria, int iAldiak);
long int liFaktoriala(int iMuga);
float fKosinuaKalkulatu(float fX);


int main()
{
    float fAng, fX, fKosinua;

    printf("1. koadranteko angelu baten kosinua kalkulatu %.4f prezisioarekin\n\n", EPSILON);

    do
    {
        printf("1. koadranteko angelua graduetan: ");
        scanf("%f", &fAng);
    } while (fAng < 0.0 || fAng >= 90.0);

    fX = fAng * 2 * M_PI / 360; // graduak radianetara bihurtu
    printf("Angelua radianetan: %8.5f\n", fX);

    fKosinua = fKosinuaKalkulatu(fX);

    printf("\n");
    printf("Gure programaz lortutako kosinua[%.3f gradu] -----> %7.5f\n", fAng, fKosinua);
    printf("cos() funtzioak ematen duena cos(%.3f gradu) -----> %7.5f\n", fAng, cos(fX));

    printf("\nRETURN tekla sakatu programatik irteteko\n");
    getchar();
    return 0;
}


// berreketa kalkulatzeko funtzioa
float fBerreketa(float fOinarria, int iAldiak)
{
    float fMetagailua = 1.0;
    int i;

    for (i = 0; i < iAldiak; i++)
    {
        fMetagailua *= fOinarria;
    }
    return fMetagailua;
}


// faktoriala kalkulatzeko funtzioa
long int liFaktoriala(int iMuga)
{
    long int liMetagailua = 1;
    int i;

    for (i = 1; i <= iMuga; i++)
    {
        liMetagailua *= i;
    }
    return liMetagailua;
}

// kosinua kalkulatzeko funtzioa Taylor seriea erabiliz
float fKosinuaKalkulatu(float fX)
{
    int iKont = 0;
    float fKosinua = 0.0;
    float fBatugai = 1.0;
    long int liFaktoreak;
    float fBerredura;
    float fZeinua;

    while (fabs(fBatugai) > EPSILON)
    {
        fKosinua += fBatugai;
        iKont += 2;

        liFaktoreak = liFaktoriala(iKont);
        fBerredura = fBerreketa(fX, iKont);
        fZeinua = fBerreketa(-1, iKont / 2);

        fBatugai = fZeinua * fBerredura / liFaktoreak;
        printf("%d. iterazioan, batugaia ===> %8.5f, aldea ===> %8.5f\n", iKont / 2, fBatugai, fabs(fabs(fBatugai) - EPSILON));
    }
    return fKosinua;
}
Programaren lehen hurbilketa honek fX sarrerako angelua 0 eta Π/2 artekoa izan dadila. Gero, programa ongi dabilenean kodifikazioa aberastu edozein koadranteko angelurako, hau da sarrerako fX angelua 0 eta artekoa izan daitekeela. Amaitzeko, programa osatu edozein angelurako, hots, sarrerako fX angelua baino handiagoa denean ere, laguntza hemen: Ariketa 42 | Taylor azpiprogramaz (edozein angelurako).


Demagun orain bigarren bertsio honetan aldaketa bat egingo dugula: programa nagusiak beste emaitza bat agertu behar duela ere (iterazioen kopurua). Beraz, kosinua kalkulatzeko metodo bera erabiliko dugu baina azpiprogramak itzuli beharko dituen emaitzak bi izango dira:
  1. Kosinuaren balioa, eta horrez gain
  2. Zenbat iteraziotan lortu den kalkulatzea
Kasu honetan batukaria kalkulatzen duen azpiprogramak bi emaitza itzuli behar dituelako ezingo da funtzioaren return bitartez biak kanporatu. Funtzio honek parametroak erabiliko ditu emaitzak kanporatzeko, bere prototipoa hau izango da:
void KosinuaKalkulatu(float fX, float *fKosinua, int *iIterazioKopurua);

 Sarrera: rX angelua radianetan (gogoratu bertsio honetan doikuntza konstante bat dela)
 Irteera: fKosinua kosinuaren kalkulua
 Irteera: iIterazioKopurua iterazioen kopurua

Hauxe da bigarren bertsioaren programa:

/* Ariketa-41a2_TaylorKosinua_1_koadrantea: kosinua Taylor bitartez. */

// 1. koadranteko angelu bat teklatuz eman eta dagokion kosinua
// kalkulatuko da Taylor segida jarraituz.

// Erabilitako funtzioak eta itzulitako datu-motak:
//   liFaktoriala() -------> long int
//   fBerreketa() ---------> float
//   KosinuaKalkulatu() ---> void (bi emaitzak parametroen bidez)

#include <stdio.h>
#include <math.h>    // M_PI konstanterako

#define EPSILON 0.0005  // bost hamarmilaren

float fBerreketa(float fOinarria, int iAldiak);
long int liFaktoriala(int iMuga);
void KosinuaKalkulatu(float fX, float *fKosinua, int *iIterazioKopurua);


int main()
{
    float fAng, fX, fKosinua;
    int iIterazioKopurua;

    printf("1. koadranteko angelu baten kosinua kalkulatu %.4f prezisioarekin\n\n", EPSILON);

    do
    {
        printf("Lehenengo koadranteko angelua graduetan: ");
        scanf("%f", &fAng);
    } while (fAng < 0.0 || fAng > 90.0);

    fX = fAng * 2 * M_PI / 360.0; // graduak radianetara bihurtu

    KosinuaKalkulatu(fX, &fKosinua, &iIterazioKopurua);

    printf("\nKalkuluaren iterazioen kopurua (iIterazioKopurua) ----> %d\n", iIterazioKopurua);
    printf("Gure programaz lortutako kosinua[%.3f gradu] -------> %.5f\n", fAng, fKosinua);
    printf("cos() funtzioak ematen duena cos(%.3f gradu) -------> %.5f\n", fAng, cos(fX));

    printf("\nRETURN tekla sakatu programatik irteteko\n");
    getchar();

    return 0;
}


// fOinarria^iAldiak kalkulatzeko funtzioa
float fBerreketa(float fOinarria, int iAldiak)
{
    float fMetagailua = 1.0;
    int i;

    for (i = 0; i < iAldiak; i++)
    {
        fMetagailua *= fOinarria;
    }
    return fMetagailua;
}


// iMuga! kalkulatzeko funtzioa
long int liFaktoriala(int iMuga)
{
    long int liMetagailua = 1;
    int i;

    for (i = 1; i <= iMuga; i++)
    {
        liMetagailua *= i;
    }
    return liMetagailua;
}


// kosinua kalkulatzeko funtzioa Taylor seriea erabiliz
void KosinuaKalkulatu(float fX, float *fKosinua, int *iIterazioKopurua)
{
    int iKont = 0;
    *fKosinua = 0.0;
    float fBatugai = 1.0;
    long int liFaktoreak;
    float fBerredura;
    float fZeinua;

    while (fabs(fBatugai) > EPSILON)
    {
        *fKosinua += fBatugai;
        iKont += 2;

        liFaktoreak = liFaktoriala(iKont); // faktorialaren deia
        fBerredura = fBerreketa(fX, iKont);  // berreketaren deia
        fZeinua = fBerreketa(-1, iKont / 2); // zeinua kalkulatzeko

        fBatugai = fZeinua * fBerredura / liFaktoreak;
        printf("%d. iterazioan, batugaia ===> %8.5f, aldea ===> %7.5f\n", iKont / 2, fBatugai, fabs(fabs(fBatugai) - EPSILON));
    }

    *iIterazioKopurua = iKont / 2;
}
Programaren bigarren bertsio honetan jarraituko dugu fX sarrerako angelua 0 eta Π/2 artekoa izaten. Gero, 90 graduraino ongi dabilenean kodifikazioa aberastu edozein koadranteko angelurako, hau da sarrerako fX angelua 0 eta artekoa izan daitekeela. Amaitzeko, edozein angelurako programa osatu, hots, sarrerako fX angelua baino handiagoa denean ere, laguntza hemen: Ariketa 42 | Taylor azpiprogramaz (edozein angelurako).

Lehen eta bigarren bertsio hauekin erdibideko soluzio bat programa daiteke. Alegia, programaren bi emaitzetatik bat return aginduaren bitartez itzuli eta beste emaitza irteerako parametro bezala kanporatzea. Horrela planteaturiko funtzioari bi prototipo hauek dagozkio:

float fKosinuaKalkulatu(float fX, int *iIterazioKopurua);

Sarrera: fX radianak (teklatuz irakurritako rAngelua graduak radianetara igarota)
Irteera: float, emandako angeluari dagokion kosinua Taylor bitartez
Irteera: iIterazioKopurua Taylor bitartez kosinua lortzeko behar izan diren iterazioak

Bigarren aukeran return bitartez iterazioak itzultzun ditu funtzioak:

int fKosinuaKalkulatu(float fX, float *fKosinua);

Sarrera: fX radianak (teklatuz irakurritako rAngelua graduak radianetara igarota)
Irteera: fKosinua angeluari dagokion kosinua Taylor bitartez
Irteera: int, Taylor bitartez kosinua kalkulatzeko behar izan diren iterazioak



Programaren hirugarren bertsio honek fX sarrerako angelua 0 eta Π artekoa izan dadila. Ikus daiteke 160.8 graduko angeluarekin programa ondo dabilela, baina 160.9 graduko angeluarekin programa txarto dabilela. Beraz, sarrerako x angelua edozein izan dadin programa berezitu bat idazte komeni zaigu, hauxe: Ariketa 42 | Taylor azpiprogramaz (edozein angelurako).

Hauxe da hirugarren bertsioaren programa:

/* Ariketa-41c_TaylorKosinua_1-2_koadranteak: kosinua Taylor bitartez. */

// 1. eta 2. koadranteetako angelu bat teklatuz eman eta 
// dagokion kosinua kalkulatuko da Taylor segida jarraituz.

// Erabilitako funtzioak eta itzulitako datu-motak:
//   liFaktoriala() --------> long int
//   fBerreketa() ----------> float
//   fKosinuaKalkulatu() ---> float

#include <stdio.h>
#include <math.h>    // M_PI konstanterako

#define EPSILON 0.0005  // bost hamarmilaren

long int liFaktoriala(int iMuga);
float fBerreketa(float fOinarria, int iAldiak);
float fKosinuaKalkulatu(float fX);


int main()
{
    float fAng, fX, fKosinua;

    printf("Lehen bi koadranteetako angelu baten kosinua kalkulatu %0.4f prezisioarekin\n", EPSILON);
    printf("KONTUZ! Angeluak 160 gradu baino gehiago balio badu faktorialak alde egiten du\n\n");

    do {
        printf("0 eta 180 arteko angelua graduetan: ");
        scanf("%f", &fAng);
    } while (fAng < 0.0 || fAng >= 180.0);

    fX = fAng * 2 * M_PI / 360; // Graduak radianetara bihurtu
    printf("Angelua radianetan: %.5f\n", fX);

    fKosinua = fKosinuaKalkulatu(fX);

    printf("\nGure programaz lortutako kosinua[%.3f gradu] -----> %.5f\n", fAng, fKosinua);
    printf("cos() funtzioak ematen duena cos(%.3f gradu) -----> %.5f\n", fAng, cos(fX));

    printf("\nRETURN tekla sakatu programatik irteteko\n");
    getchar();
    return 0;
}


// faktoriala kalkulatzeko funtzioa
long int liFaktoriala(int iMuga)
{
    long int liMetagailua = 1;
    int i;

    for (i = 1; i <= iMuga; i++)
    {
        liMetagailua *= i;
    }
    return liMetagailua;
}


// berredura kalkulatzeko funtzioa
float fBerreketa(float fOinarria, int iAldiak)
{
    float fMetagailua = 1.0;
    int i;

    for (i = 0; i < iAldiak; i++)
    {
        fMetagailua *= fOinarria;
    }
    return fMetagailua;
}


// Taylor seriea erabiliz kosinua kalkulatzeko funtzioa
float fKosinuaKalkulatu(float fX)
{
    int iKont = 0;
    float fKosinua = 0.0;
    float fBatugai = 1.0;
    long int liFaktoreak;
    float fBerredura;
    float fZeinua;

    printf("\nKONTUZ!!! 160 gradu baino angelu handiagoekin faktorialak alde egiten du\n\n");
    printf("%34s %20s %15s\n", "Faktoriala", "Berredura", "Batugaia");
    printf("%34s %20s %15s\n", "----------", "---------", "--------");

    while (fabs(fBatugai) > EPSILON)
    {
        fKosinua += fBatugai;
        iKont += 2;

        liFaktoreak = liFaktoriala(iKont);
        fBerredura = fBerreketa(fX, iKont);
        fZeinua = fBerreketa(-1, iKont / 2);

        fBatugai = fZeinua * fBerredura / liFaktoreak;
        printf("%2d. iterazioan =====> %12ld %20.5f %15.5f\n", iKont / 2, liFaktoreak, fBerredura, fBatugai);
    }
    return fKosinua;
}







  • Ariketa-41a1_TaylorKosinua_1_koadrantea.cbp | main.c  
  • Ariketa-41a2_TaylorKosinua_1_koadrantea.cbp | main.c  
  • Ariketa-41b1_TaylorSinua_1_koadrantea.cbp | main.c       (do-while)
  • Ariketa-41b2_TaylorSinua_1_koadrantea.cbp | main.c       (while)
  • Ariketa-41c_TaylorKosinua_1-2_koadranteak.cbp | main.c  


 

Ariketa 40 | Fibonacci-ren zenbakiak azpiprogramaz

ZER DAKIDAN:
Fibonacci matematikariaren sekuentza ezagutzen dut, lehen zenbakia 0 da eta bigarrena 1 da, hurrengoak lortzeko aurreko bi zenbakien batura egin behar da.



ZER IKASIKO DUDAN:
Fibonacci sekuentziako zenbakiak lortzen ikasiko dut baina funtzioak erabiliz.





Leonardo Pisano (Pisa, Italia, 1170-1250), Leonardo Bonacci, Leonardo Fibonacci edo Fibonacci moduan ezaguna, Italiar matematikaria izan zen, Erdi Aroko ezagunetarikoa. Ezaguna da batez ere bi aurkikuntzengatik:

  • Hindu-arabiar zenbaki sistema Europan sartu zuen eta berau erabiltzeko bideak jarri zituen XIII. mendeko "Liber Abaci" liburuaren bitartez
  • Fibonacciren zenbakiak deskribatu zituen liburu berean, nahiz eta berak ez zituen aurkitu baizik eta adibide moduan jarri
Leonardo Pisano, Fibonacci, ezagutzeko hemen duzu artikulu bat Fibonacci, el matemático que se puso a contar conejos y descubrió la secuencia divina.


Fibonacciren sekuentziako lehen zenbakia 0 da, Fibonacci-ren bigarren zenbakia 1 da, eta hirugarren zenbakia lortzeko aurreko biak batuko dira, horregatik Fibonacciren hirugarren zenbakia 1 da, laugarren zenbakia 2 izango da, bosgarrena 3, ... 

Beraz, Fibonacciren sekuentzia honako hau da:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, ...


Ondorengoa da Fibonacciren segidaren adierazpen orokorra:

{\displaystyle F_{n}={\begin{cases}0&n=0{\mbox{ bada}}\\1&n=1{\mbox{ bada}}\\F_{n-1}+F_{n-2}&n>1{\mbox{ bada}}\\\end{cases}}}


Fibonacciren zenbakiak grafikoki adieraztean honako blokeen sorta eta espirala lortzen dira:




Fibonacciren sekuentziako bi zenbaki hartuz eta zatiketa eginez, urrezko zenbakia edo jainkozko proportzioa edo urrezko proportzioa edo zerutiar zenbakia lortzen da:

Fibonacciren sekuentzia sarritan agertzen da naturan. Izan ere, naturan hazkundea gertatzen denean Fibonacciren sekuentziaren arabera ematen da:

     

     

     

    





Eskatzen den programa (bi funtzio)

Programa bakarra izan arren programak bi zati izango ditu. Lehen zatian emaitzik itzultzen ez duen funtzio bati dei egingo zaio eta programaren bigarren zatian zenbaki bat itzultzen duen funtzio bati dei egingo zaio.

Hau garrantzitsua da

Ez ahaztu, edozein ariketa programatzerakoan beti main() funtzio nagusitik hasiko garela, eta main() funtzio nagusia bukatzean jarraituko dugula azpiprograma guztien kodea idazten. Horregatik, bi adibide hauetan main() funtzio nagusiak ematen dira eta eskatzen da garatzea bakoitzari dagokion azpiprograma.



Lehen zatia. Fibonacciren sekuentzia osatuko duten zenbakien iZenbat kopurua teklatuz irakurri programa nagusian eta funtzio batek ondoko taularen pantailaraketa egin dezala FOR-DO egitura bat erabiliz, funtzioaren izena FibonaccirenSekuentziaPantailaratu() izan daiteke.

Hona hemen kodifikazioa non programa nagusia ematen den eta funtzioa falta den:

/* Ariketa-40a_FibonacciAzpiprogramaz: ezer itzultzen ez duen funtzioa. */

// Zenbaki osoekin lan eginez, FibonaccirenSekuentziaPantailaratu() funtzioak lan
// bat burutzen du (pantailaraketa) baina ez dio ezer itzultzen programa nagusiari. 

#include <stdio.h>

#define ZENBAKIKOPURUMAX 23 // Fibonacci zenbakien gehienezko kopurua

// Fibonacci sekuentzia pantailaratzeko funtzioa
void FibonaccirenSekuentziaPantailaratu(int iZenbat)
{
    // funtzioaren kodea hemen
}


// iKopurua (3 eta 24 artekoa) teklatuz irakurri eta Fibonacci zenbakien
// sekuentziaren horrenbeste elementu pantailaratuko dira 0-tik hasita
int main()
{
    int iKopurua;

    printf("\n\n");

    // zenbaki kopurua eskatu eta baieztatu
    do
    {
        printf("Fibonacci zenbakien kopurua eman (3 eta %d artekoa)\n", ZENBAKIKOPURUMAX);
        printf("eta 0-tik hasita Fibonacciren segida erakutsiko da: ");
        scanf("%d", &iKopurua);
    } while (iKopurua < 3 || iKopurua > ZENBAKIKOPURUMAX);

    // Fibonacci sekuentzia pantailaratu
    FibonaccirenSekuentziaPantailaratu(iKopurua);

    printf("\nPrograma bukatu da, irteteko RETURN sakatu\n");
    getchar(); // Return tekla itxaron

    return 0;
}

Programaren lehen zatiko irteera bat hau izan daiteke:




Bigarren zatia. Prozesu errepikakor bat izango da eta bertatik irteteko b edo B erantzun beharko da, bestela programa nagusian iMuga teklatuz irakurriko da eta funtzio batek kalkulatuko du 0-tik hasita zenbat Fibonacciren zenbaki dauden. Horretarako, WHILE-DO egitura bat edo DO_WHILE egitura bat erabiliko da fniFibonacciZenbakienKopuruaKalkulatu() izeneko funtzioan.

Hona hemen fniFibonacciZenbakienKopuruaKalkulatu() funtzioa bi modutan programatuta:

/* Ariketa-40b1_FibonacciAzpiprogramaz */

// Fibonacci zenbakien kopurua kalkulatzeko funtzioa
int FibonacciZenbakienKopuruaKalkulatu(int iMuga)
{
    int iFibo1 = 0, iFibo2 = 1, iFibo3 = iFibo1 + iFibo2;
    int iFiboKopuru;

    if (iMuga == 0)
        iFiboKopuru = 1;  // ez da while barrura sartuko
    else
        iFiboKopuru = 2;  // hasieraketa, while barruan inkrementatuko da

    iFibo1 = 0;
    iFibo2 = 1;
    iFibo3 = iFibo1 + iFibo2;
    while (iFibo3 <= iMuga)
    {
        iFibo1 = iFibo2;
        iFibo2 = iFibo3;
        iFibo3 = iFibo1 + iFibo2;
        iFiboKopuru++;
    }

    return iFiboKopuru;
}
/* Ariketa-40b2_FibonacciAzpiprogramaz */

// Fibonacci zenbakien kopurua kalkulatzeko funtzioa
void FibonacciZenbakienKopuruaKalkulatu(int iMuga, int *iFiboKopuru)
{
    int iFibo1 = 0, iFibo2 = 1, iFibo3 = iFibo1 + iFibo2;

    if (iMuga == 0)
        *iFiboKopuru = 1;  // ez da while barrura sartuko
    else
        *iFiboKopuru = 2;  // hasieraketa, while barruan inkrementatuko da

    iFibo1 = 0;
    iFibo2 = 1;
    iFibo3 = iFibo1 + iFibo2;
    while (iFibo3 <= iMuga)
    {
        iFibo1 = iFibo2;
        iFibo2 = iFibo3;
        iFibo3 = iFibo1 + iFibo2;
        (*iFiboKopuru)++;
    }
}

Programaren bigarren zatiko irteera bat hau izan daiteke:




Goiko bi programa horiek bukatu ondoren, saiatu zaitez bi ariketak programa bakar batean biltzen, hots, funtzionalitate guztiak betetzen dituen Programa Nagusi berria idatzi eta bi azpiprogramen kodea inportatu.







  • Ariketa-40a_FibonacciAzpiprogramaz.cbp | main.c
  • Ariketa-40b1_FibonacciAzpiprogramaz.cbp | main.c
  • Ariketa-40b2_FibonacciAzpiprogramaz.cbp | main.c
  • Ariketa-40c_FibonacciAzpiprogramaz.cbp | main.c       (errekurtsibitatea)