errepikakorrak etiketadun mezuak erakusten. Erakutsi mezu guztiak
errepikakorrak etiketadun mezuak erakusten. Erakutsi mezu guztiak

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

Ariketa 33 | Fibonacci-ren zenbakiak

ZER DAKIDAN:
Dagoeneko for, do-while eta while agindu errepikakorra erabili ditut. Baina bakoitza edozein egoeratan erabil baiteke?



ZER IKASIKO DUDAN:
Prozesu errepikorraren iterazio kopurua ezaguna denean for agindu errepikakorra erabiliko dut. Aldiz, prozesu errepikorraren iterazio kopurua ezezaguna denean, do-while edo while agindu errepikakorrek erabiliko ditut.


Ariketa:
Teklatuaren bitartez N kopuru oso bat irakurri eta Fibonacci-ren lehen N zenbakiak pantailaratu. Fibonacci-ren lehen zenbakia 0 da, Fibonacci-ren bigarren zenbakia 1 da, eta hirugarren zenbakia lortzeko aurreko biak batuko dira, horregatik Fibonacci-ren hirugarren zenbakia 1 da, laugarren zenbakia 2 izango da, bosgarrena 3, ... 
Beraz, Fibonacci-ren sekuentzia honako hau da:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

Programaren exekuzio batean N kopurua 9 balitz, bere irteera  0, 1, 1, 2, 3, 5, 8, 13, 21, izango litzateke.

Hauxe 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}}}




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

Leonardo Pisano, Fibonacci, ezagutzeko artikulu bat "Fibonacci, el matemático que se puso a contar conejos y descubrió la secuencia divina" eta hemen Fibonacci-ren sekuentziaren adibide bat naturan:



Goiko azalpenean egiten den bezala, Fibonacci zenbakien iZenbat kopurua teklatuz irakurri eta for egitura erabiliz ondoko taula pantailaratu, programan errepikatzen den prozesua hauxe dela:
    for (iKont=3; iKont<=iZenbat; iKont++)
    {
        iFiboBerria = iFibo1 + iFibo2;
        fUrrezkoProportzioa = (float)iFiboBerria / iFibo2;
        printf("\n %12d %20d %28.7f", iKont, iFiboBerria, fUrrezkoProportzioa);
        iFibo1 = iFibo2;
        iFibo2 = iFiboBerria;
    }
Lehen programaren irteera hau izan dadila:

Datua 15 izanik lortzen den Fibonacci-ren segida eta Urrezko Proportzioa goiko irudikoak dira




Aurreko bezalakoa da, hots, Fibonacci-ren sekuentzia pantailaratu nahi da. Baina, programak prozesu errepikakor nagusi bat izango du eta laster ikasiko dugun char datu-motako aldagai batek kontrolatuko du programaren amaitzea. Lehen bezala, iZenbat kopurua teklatuz irakurri eta for egitura erabiliz Fibonacci-ren zenbakiak pantailaratu dira, programan errepikatzen den prozesua hauxe dela:
        printf("\n\n 0, 1");
        iFibo1 = 0;
        iFibo2 = 1;
        for (iKont=3; iKont<=iZenbat; iKont++)
        {
            iFiboBerria = iFibo1 + iFibo2;
            iFibo1 = iFibo2;
            iFibo2 = iFiboBerria;
            printf(", %d", iFiboBerria);
        }
        printf(".");
Kalkuluen errepikapenak egiten dira eta prozesu errepikakorra kontrolatzeko aldagaiaren datu-mota char da (datu-mota berria da guretzat eta laster ikasiko dugu). Bigarren programaren irteera hau izan dadila, ikusi prozesua errepikatzen dela b edo B erantzun arte:

Datua 20 izanik lortzen den Fibonacci-ren segida goiko irudikoa da



Hirugarren programan iZbk teklatuz irakurri eta datu hori Fibonacci-ren segidako zenbaki bat den ala ez aztertu beharko da:
        iFibo1 = 0;
        iFibo2 = 1;
        iFibo3 = iFibo1 + iFibo2;
        iIterazio = 3;
        while (iFibo3 < iZbk)
        {
           iFibo1 = iFibo2;
           iFibo2 = iFibo3;
           iFibo3 = iFibo1 + iFibo2;
           iIterazio++;
        }
        if (iFibo3 == iZbk)
            printf("Bai, bada");
        else
            printf("Ez, ez da");
Hirugarren programaren irteera hau izan dadila, ikusi kalkuluak errepikatzen direla b edo B erantzun arte:

while (iFibo3<iZbk) eteten da iFibo3==iZbk delako

while (iFibo3<iZbk) eteten da iFibo3>iZbk delako






  • Ariketa-33a_FibonacciZenbakiak.cbp | main.c  
  • Ariketa-33b_FibonacciZenbakiak.cbp | main.c  
  • Ariketa-33c_FibonacciZenbakiak.cbp | main.c  


 

Ariketa 32 | Biderkari bat kalkulatzen

ZER DAKIDAN:
Dagoeneko for, do-while eta while agindu errepikakorra erabili ditut. Baina bakoitza edozein egoeratan erabil baiteke?



ZER IKASIKO DUDAN:
Prozesu errepikorraren iterazio kopurua ezaguna denean for agindu errepikakorra erabiliko dut. Aldiz, prozesu errepikorraren iterazio kopurua ezezaguna denean, do-while edo while agindu errepikakorrek erabiliko ditut.


Teklatuaren bitartez N zenbaki osoa eta positiboa irakurriz ondoko biderkariaren emaitza lortu:
Hau da, biderkagaien kopurua ezaguna denez FOR-DO agindua erabili ahal izango da, sarrerako datua 5 denean biderkaria hau delarik:

        (1 - 1/4) * (1 + 1/9) * (1 - 1/16) * (1 + 1/25) * ...
/* Ariketa-32a_Biderkaria_for: iterazio-kopuru ezaguna */

//----------------------------------------------------------------
// iMuga emanda biderkaria lortu:

//     fBiderkaria = (1 - 1/4) * (1 + 1/9) * (1 - 1/16) *  ...
//    iKontagailua ---->   2           3           4
//----------------------------------------------------------------

#include <stdio.h>

int main()
{
    int iMuga, iKontagailua;
    float fZeinua, fBiderkagaia, fBiderkaria;

    do  // mugaren balioa eskatu
    {
        printf("Muga adierazten duen zenbaki osoa eta positiboa eman: ");
        scanf("%d", &iMuga);
    } while (iMuga <= 0);

    printf("\n");

    // hasierako balioak
    fBiderkaria = 1.0;
    fZeinua = 1.0;

    for (iKontagailua = 2; iKontagailua <= iMuga; iKontagailua++)
    {
        fBiderkagaia = 1 - fZeinua / (iKontagailua * iKontagailua);
        fBiderkaria *= fBiderkagaia;

        printf("%3d. itzulian --->    Zeinua=%2.0f    Biderkagaia=%0.4f    Biderkaria=%0.4f\n",
               iKontagailua, fZeinua, fBiderkagaia, fBiderkaria);

        fZeinua *= -1; // zeinua aldatu
    }

    printf("\nBiderkaria = %0.4f\n", fBiderkaria);
    printf("\n");
    printf("=======================\n");
    printf("RETURN sakatu amaitzeko\n");
    printf("=======================\n");

    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}


Bigarren biderkari hau kalkulatzerakoan ez digute ematen biderkagaien kopurua. Horren ordez erabiltzaileak hauta dezake bi biderkarien (bi emaitzen) arteko aldea zein txikia izango den, hots, zenbat eta biderkagai gehiago aintzat hartu biderkaria zehatzagoa da baina gero eta garrantzi txikiago du beste biderkagai berri bat biderkatzeak. Hortaz, biderkagaiak joan biderkatzen jarraian erakusten den baldintza bete arte Abs(rAzkenEmaitza - rAurrekoEmaitza) < rDiferentzia non rDiferentzia teklatuaren bitartez irakurritako zenbaki erreala eta positiboa den, eta rAzkenEmaitza zein rAurrekoEmaitza programan kalkulatutako balioak diren.

Hona hemen batukaria do-while aginduaren bitartez kalkulatzen duen Ariketa-31b_Batukaria_do-while programaren kodea:

/* Ariketa-32b_Biderkaria_do-while: iterazio-kopuru ezezaguna */

//----------------------------------------------------------------
// Bi emaitzen arteko diferentzia emanda fBiderkaria lortu:
//     fBiderkaria = (1 - 1/4) * (1 + 1/9) * (1 - 1/16) *  ...
//    iKontagailua ---->   2           3           4
// Prozesu errepikorraren iterazio kopurua ez da ezagutzen. Hori
// dela eta, ariketa hau ezin daiteke egin for egitura erabiliz.
//----------------------------------------------------------------

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

int main()
{
    int iKontagailua;
    float fZeinua, fDiferentzia, fBiderkagaia, fBiderkaria, fAurrekoEmaitza, fAzkenEmaitza;

    do  // bi emaitzen arteko gehienezko diferentzia eskatu
    {
        printf("Eman bi emaitzen arteko diferentzia maximoa (adibidez, 0.003): ");
        scanf("%f", &fDiferentzia);
    } while (fDiferentzia <= 0);

    printf("\n");

    // hasierako balioak
    fBiderkaria = 1.0;
    fZeinua = 1.0;
    iKontagailua = 2;

    // lehen kalkulua begiztatik kanpo
    fBiderkagaia = 1 - fZeinua / (iKontagailua * iKontagailua);
    fBiderkaria *= fBiderkagaia;
    printf("%3d. itzulia  begiztatik kanpo,           Biderkaria=%0.4f\n", iKontagailua, fBiderkaria);

    do  // kalkulua egiten jarraitu diferentziaren irizpidea betetzen den arte
    {
        fAurrekoEmaitza = fBiderkaria;
        fZeinua *= -1; // Zeinua aldatu
        iKontagailua++;
        fBiderkagaia = 1 - fZeinua / (iKontagailua * iKontagailua);
        fBiderkaria *= fBiderkagaia;
        fAzkenEmaitza = fBiderkaria;

        printf("%3d. --->  Zeinua=%2.0f  Biderkagaia=%0.4f  Biderkaria=%0.4f  Diferentzia=%0.4f\n",
               iKontagailua, fZeinua, fBiderkagaia, fBiderkaria, fabs(fAzkenEmaitza - fAurrekoEmaitza));
    } while (fabs(fAzkenEmaitza - fAurrekoEmaitza) >= fDiferentzia);

    printf("\nBiderkaria = %0.4f\n", fBiderkaria);
    printf("\n");
    printf("=======================\n");
    printf("RETURN sakatu amaitzeko\n");
    printf("=======================\n");

    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}

Hona hemen batukaria while aginduaren bitartez kalkulatzen duen Ariketa-31c_Batukaria_while programaren kodea:

/* Ariketa-32c_Biderkaria_while: iterazio-kopuru ezezaguna */

//----------------------------------------------------------------
// Bi emaitzen arteko diferentzia emanda fBiderkaria lortu:
//     fBiderkaria = (1 - 1/4) * (1 + 1/9) * (1 - 1/16) *  ...
//    iKontagailua ---->   2           3           4
// Prozesu errepikorraren iterazio kopurua ez da ezagutzen. Hori
// dela eta, ariketa hau ezin daiteke egin for egitura erabiliz.
//----------------------------------------------------------------

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

int main()
{
    int iKontagailua;
    float fZeinua, fDiferentzia, fBiderkagaia, fBiderkaria, fAurrekoEmaitza, fAzkenEmaitza;

    printf("///////////////////////\n\n");

    do // emaitzen arteko gehienezko diferentzia eskatu
    {
        printf("Eman bi emaitzen arteko diferentzia maximoa (adibidez, 0.003): ");
        scanf("%f", &fDiferentzia);
    } while (fDiferentzia <= 0);

    printf("\n");

    // hasierako balioak
    fBiderkaria = 1.0;
    fZeinua = +1.0;
    iKontagailua = 2;

    // lehen kalkulua begiztatik kanpo
    fBiderkagaia = 1 - fZeinua / (iKontagailua * iKontagailua);
    fBiderkaria *= fBiderkagaia;
    printf("%3d. itzulia  begiztatik kanpo,         Batukaria=%7.4f\n", iKontagailua, fBiderkaria);
    fAurrekoEmaitza = fBiderkaria;

    // bigarren kalkulua begiztatik kanpo
    fZeinua = -1.0;
    iKontagailua = 3;
    fBiderkagaia = 1 - fZeinua / (iKontagailua * iKontagailua);
    fBiderkaria *= fBiderkagaia;
    printf("%3d. itzulia  begiztatik kanpo,         Batukaria=%7.4f\n", iKontagailua, fBiderkaria);
    fAzkenEmaitza = fBiderkaria;

    while (fabs(fAzkenEmaitza - fAurrekoEmaitza) > fDiferentzia)
    {
        fAurrekoEmaitza = fBiderkaria;
        fZeinua *= -1; // zeinua aldatu
        iKontagailua++;
        fBiderkagaia = 1 - fZeinua / (iKontagailua * iKontagailua);
        fBiderkaria *= fBiderkagaia;
        fAzkenEmaitza = fBiderkaria;

        printf("%3d. -->  Zeinua=%2.0f  Biderkagaia=%7.4f  Biderkaria=%7.4f  Dif.=%7.4f\n",
               iKontagailua, fZeinua, fBiderkagaia, fBiderkaria, fabs(fAzkenEmaitza - fAurrekoEmaitza));
    }

    printf("\n");
    printf("Biderkaria = %.4f\n", fBiderkaria);
    printf("\n");
    printf("=======================\n");
    printf("RETURN sakatu amaitzeko\n");
    printf("=======================\n");

    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}






  • Ariketa-32a_Biderkaria_for.cbp | main.c
  • Ariketa-32b_Biderkaria_do-while.cbp | main.c
  • Ariketa-32c_Biderkaria_while.cbp | main.c


 

Ariketa 31 | Batukari bat kalkulatzen

ZER DAKIDAN:
Dagoeneko for, do-while eta while agindu errepikakorra erabili ditut. Baina bakoitza edozein egoeratan erabil baiteke?



ZER IKASIKO DUDAN:
Prozesu errepikorraren iterazio kopurua ezaguna denean for agindu errepikakorra erabiliko dut. Aldiz, prozesu errepikorraren iterazio kopurua ezezaguna denean, do-while edo while agindu errepikakorrek erabiliko ditut.


Teklatuaren bitartez S zenbaki osoa eta positiboa irakurriz ondoko batukariaren emaitza lortu:
Argi dagoenez, batugaien kopurua ezaguna denez for agindua erabili ahal izango da, sarrerako datua 7 denean batukaria hau delarik:

    -1/1    +1/4    -1/9    +1/16    -1/25    +1/36    -1/49
/* Ariketa-31a_Batukaria_for: iterazio-kopuru ezaguna */

//-----------------------------------------------------------------------------------
// iMuga emanda batukaria lortu:   fBatukaria = -1/1 +1/4 -1/9 + ... +1/(iMuga*iMuga)
//-----------------------------------------------------------------------------------

#include <stdio.h>

int main()
{
    int iMuga, iKontagailua;
    double fZeinua, fBatugaia, fBatukaria;

    printf("///////////////////////\n\n");

    do  // muga eskatu
    {
        printf("Muga adierazten duen zenbaki osoa eta positiboa eman: ");
        scanf("%d", &iMuga);
    } while (iMuga <= 0);

    printf("\n");

    fBatukaria = 0.0; // batukariaren hasierako balioa
    fZeinua = -1.0;   // hasierako zeinua

    // kalkulua burutu iterazio koputu jakin baten bidez
    for (iKontagailua = 1; iKontagailua <= iMuga; iKontagailua++)
    {
        fBatugaia = fZeinua / (iKontagailua * iKontagailua);
        fBatukaria += fBatugaia;

        printf("%3d. itzulian --->    Zeinua=%2.0f    Batugaia=%7.4f    Batukaria=%7.4f\n",
               iKontagailua, fZeinua, fBatugaia, fBatukaria);

        fZeinua *= -1; // Zeinua aldatzea
    }

    printf("\n");
    printf("Batukaria = %.4f\n", fBatukaria);

    printf("\n");
    printf("=======================\n");
    printf("RETURN sakatu amaitzeko\n");
    printf("=======================\n");

    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}


Batukari hau kalkulatzerakoan ez digute ematen batugaien kopurua. Horren ordez, bi batukarien arteko aldea zein txikia izango den erabiltzaileak hautatuko du, hots, zenbat eta batugai gehiago gehitu batukaria zehatzagoa da, baina beste batugai berri bat gehitzeak gero eta garrantzi txikiago du. Hortaz, baldintza honelako zerbait izango da: batugaiak joan gehitzen ondokoa bete arte fabs(fAzkenEmaitza - fAurrekoEmaitza) < fDiferentzia non fDiferentzia teklatuaren bitartez irakurritako zenbaki erreala eta positiboa den, eta fAzkenEmaitza zein fAurrekoEmaitza programan kalkulatutako balioak diren.
Iterazio jakin batean uneko batukaria fAzkenEmaitza da eta aurreko iterazioan batukaria fAurrekoEmaitza da, balio bien arteko diferentzia txikia izatean (adibidez 0.02) prozesu errepikakorra eten egingo da

Hona hemen batukaria do-while aginduaren bitartez kalkulatzen duen Ariketa-31b_Batukaria_do-while programaren kodea:

/* Ariketa-31b_Batukaria_do-while: iterazio-kopuru ezezaguna */

//----------------------------------------------------------------
// Bi emaitzen arteko diferentzia emanda fBatukaria lortu:
//       fBatukaria = -1/1 +1/4 -1/9 +1/16 -1/25 + ...

// Prozesu errepikorraren iterazio kopurua ez da ezagutzen. Hori 
// dela eta, ariketa hau ezin daiteke egin for egitura erabiliz.
//----------------------------------------------------------------

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

int main()
{
    int iKontagailua;
    float rZeinua, fDiferentzia, fBatugaia, fBatukaria, fAurrekoEmaitza, fAzkenEmaitza;

    printf("///////////////////////\n\n");

    do  // emaitzen arteko gehienezko diferentzia eskatu
    {
        printf("Eman bi emaitzen arteko diferentzia maximoa (adibidez, 0.003): ");
        scanf("%f", &fDiferentzia);
    } while (fDiferentzia <= 0);

    printf("\n");

    // hasierako balioak
    fBatukaria = 0.0;
    rZeinua = -1.0;
    iKontagailua = 1;
    fBatugaia = rZeinua / (iKontagailua * iKontagailua);
    fBatukaria += fBatugaia;

    printf("%3d. itzulia  begiztatik kanpo,         Batukaria=%7.4f\n", iKontagailua, fBatukaria);

    do // kalkulua egiten jarraitu diferentziaren irizpidea betetzen den arte
    {
        fAurrekoEmaitza = fBatukaria;

        rZeinua *= -1; // Zeinua aldatu
        iKontagailua++;
        fBatugaia = rZeinua / (iKontagailua * iKontagailua);
        fBatukaria += fBatugaia;
        fAzkenEmaitza = fBatukaria;

        printf("%3d. --->  Zeinua=%2.0f  Batugaia=%7.4f  Batukaria=%7.4f  Diferentzia=%7.4f\n",
               iKontagailua, rZeinua, fBatugaia, fBatukaria, fabs(fAzkenEmaitza - fAurrekoEmaitza));
    } while (fabs(fAzkenEmaitza - fAurrekoEmaitza) >= fDiferentzia);

    printf("\n");
    printf("Batukaria = %.4f\n", fBatukaria);
    printf("\n");
    printf("=======================\n");
    printf("RETURN sakatu amaitzeko\n");
    printf("=======================\n");

    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}

Hona hemen batukaria while aginduaren bitartez kalkulatzen duen Ariketa-31c_Batukaria_while programaren kodea:

/* Ariketa-31c_Batukaria_while: iterazio-kopuru ezezaguna */

//----------------------------------------------------------------
// Bi emaitzen arteko diferentzia emanda fBatukaria lortu:
//       fBatukaria = -1/1 +1/4 -1/9 +1/16 -1/25 + ...

// Prozesu errepikorraren iterazio kopurua ez da ezagutzen. Hori 
// dela eta, ariketa hau ezin daiteke egin for egitura erabiliz.
//----------------------------------------------------------------

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

int main()
{
    int iKontagailua;
    float fZeinua, fDiferentzia, fBatugaia, fBatukaria, fAurrekoEmaitza, fAzkenEmaitza;

    printf("///////////////////////\n\n");

    do // emaitzen arteko gehienezko diferentzia eskatu
    {
        printf("Eman bi emaitzen arteko diferentzia maximoa (adibidez, 0.003): ");
        scanf("%f", &fDiferentzia);
    } while (fDiferentzia <= 0);

    printf("\n");

    // hasierako balioa
    fBatukaria = 0.0;

    // lehen kalkulua begiztatik kanpo
    fZeinua = -1.0;
    iKontagailua = 1;
    fBatugaia = fZeinua / (iKontagailua * iKontagailua);
    fBatukaria += fBatugaia;
    printf("%3d. itzulia  begiztatik kanpo,         Batukaria=%7.4f\n", iKontagailua, fBatukaria);
    fAurrekoEmaitza = fBatukaria;

    // bigarren kalkulua begiztatik kanpo
    fZeinua = +1.0;
    iKontagailua = 2;
    fBatugaia = fZeinua / (iKontagailua * iKontagailua);
    fBatukaria += fBatugaia;
    printf("%3d. itzulia  begiztatik kanpo,         Batukaria=%7.4f\n", iKontagailua, fBatukaria);
    fAzkenEmaitza = fBatukaria;

    while (fabs(fAzkenEmaitza - fAurrekoEmaitza) > fDiferentzia)
    {
        fAurrekoEmaitza = fBatukaria;
        fZeinua *= -1; // Zeinua aldatu
        iKontagailua++;
        fBatugaia = fZeinua / (iKontagailua * iKontagailua);
        fBatukaria += fBatugaia;
        fAzkenEmaitza = fBatukaria;

        printf("%3d. --->  Zeinua=%2.0f  Batugaia=%7.4f  Batukaria=%7.4f  Diferentzia=%7.4f\n",
               iKontagailua, fZeinua, fBatugaia, fBatukaria, fabs(fAzkenEmaitza - fAurrekoEmaitza));
    }

    printf("\n");
    printf("Batukaria = %.4f\n", fBatukaria);
    printf("\n");
    printf("=======================\n");
    printf("RETURN sakatu amaitzeko\n");
    printf("=======================\n");

    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}






  • Ariketa-31a_Batukaria_for.cbp | main.c
  • Ariketa-31b_Batukaria_do-while.cbp | main.c
  • Ariketa-31c_Batukaria_while.cbp | main.c


 

Ariketa 30 | Newton-en metodoa, erro karratua eta erro kuboa

ZER DAKIDAN:
Dagoeneko for, do-while eta while agindu errepikakorra erabili ditut. Baina bakoitza edozein egoeratan erabil daiteke?



ZER IKASIKO DUDAN:
Prozesu errepikakorraren iterazio kopurua ezezaguna denean, do-while edo while agindu errepikakorrak erabiliko ditut.


Newton-en hurbilketa-metodoa √n eta ∛n kalkulatzeko

Ariketa 29 | Newton-en metodoa, bigarren graduko edozein parabolarekin azaldutako ariketa erabiliko dugu zenbaki baten erro koadroa kalkulatzeko, baldin eta ax2+bx+c parabolaren koefizienteak egokiak badira.
ax2+bx+c parabola orokorraren koefizienteak hauek izanik:
  • a=1
  • b=0
  • c=-n
Ateratzen den ekuazioa x2-n=0 da (edo x2=n).
Ondorioz, x erroa n-ren erro karratua x=∓√n izango da.

Esate baterako, alboko irudian ikusten den bezala c=-2 denean, ekuazioa x2-2=0 da (edo x2=2). Horregatik x erroa, 2-ren erro karratua x=∓√2=∓1.4142 izango da.


Newton–Raphson metodoa (Newton-en metodo gisa ere ezagutzen dena) zenbakizko analisi-metodo bat da. Metodo honek funtzioen erro gero eta hobeak lortzen ditu, hau da, funtzioa zero egiten duen x balioa bilatzen du. Beste modu batez esanik, funtzioak OX ardatza mozten duen balioa (funtzioaren erroa) ematen du Newton–Raphson metodoak. Algoritmoa erroaren hurbilketa batekin hasten da eta urrats bakoitzean erroaren hurbilketa hobea lortzen du.

Aldagai bakarreko funtzio errealen kasuan honakoa da metodoa:
Izan bedi ƒ funtzioa x errealentzat definitua, eta izan bedi ƒ' bere deribatua. Erroaren hasierako hurbilketa bat behar dugu, x0. Erroaren hurbilketa horretan oinarrituz hurbilketa hobea izango den x1 honelaxe lortzen da:
Iterazioak eginez, n+1 hurbilketa n hurbilketan oinarritzen da formula honen arabera:
Formula horren zergatia geometrikoki adieraz daiteke. Hurrengo irudiko lerro urdina f(x) funtzioa da, eta lerro zuzen gorria f(x) funtzioaren tangentea (xn, f(xn)) puntuan:
Berde koloreko distantziari hobekuntza deitzen badiogu, orduan alfa angeluaren tangentea f(xn)/hobekuntza litzateke, baina tangente hori f(x) funtzioaren deribatua (xn, f(xn))puntuan da, lerro zuzen gorriaren malda alfa angeluaren tangentea da. Horregatik:
tag(alfa)= f(xn)/hobekuntza   eta aldi berean   tag(alfa)=malda= f'(xn)
beraz    f'(xn)= f(xn)/hobekuntza     (non  hobekuntza=xn-xn+1)
f'(xn)= f(xn)/(xn-xn+1)    nondik    xn-xn+1= f(xn)/f'(xn)
xn+1 = xn f(xn)/f'(xn)



n zenbaki erreal positibo baten erro koadroa kalkula dezagun. Hona hemen, Newton–Raphson metodotik eratorren formula:
xn+1 = xn f(xn)/f'(xn)

n ezaguna izanik x lortu:    x = √n
x2 = n
x2—n = 0

f(x) = x2—n
f'(x) = 2x

xi+1 = xi f(xi)/f'(xi)
xi+1 = xi - (xi2—n)/2xi



Programaren zuzentasuna konprobatzeko sqrt() funtzio estandarra aplika daiteke.

Hona hemen zenbaki baten erro karratua kalkulatzen duen Ariketa-30a_NewtonHurbilketaMetodoa programaren kodea:

/* Ariketa-30a_NewtonMetodoa-ErroKarratua: do-while */

//    Newton-Raphson metodoa
//    ----------------------
//    Xi+1 = Xi - f(Xi)/f'(Xi)
//    Xi+1 = Xi - (X¡*Xi - N) / 2*Xi
//    Xi+1 = (N/Xi + Xi) / 2

//    Irteteko baldintza, jarraitu hau betetzean:
//    fabs(Xi+1 - Xi) > fDoitasuna

//    -------

//    Bigarren graduko edozein parabola
//    Ax^2 + Bx + C = 0

//    f(x) = x^3 - N
//    f'(x) = 3x^2

//    Newton-Raphson metodoa
//    Xi+1 = Xi - f(Xi)/f'(Xi)
//    Xi+1 = Xi - (AXi^2 + BXi + C)/(2AXi + B)

//    -------

//    Bigarren graduko parabola berezia
//    A=1, B=0, C=-N  --> x^2 - N = 0

//    f(x) = x^2 - N
//    f'(x) = 2x

//    Newton-Raphson metodoa
//    Xi+1 = Xi - f(Xi)/f'(Xi)
//    Xi+1 = Xi - (Xi^2 - N)/2Xi
//    Kontuz Xi ez dadila zero izan, halakoetan
//    beste datu bat hautatu.

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

int main()
{
    double fZbk, fEmaitza, fAurrekoa;

    printf("\n");
    printf("   NEWTON vs. SQRT()\n");
    printf("   Eskuko kalkulagailu balitz bezala lan eginez\n");

    do // zero ez den zenbaki positiboa eskatu erabiltzaileari
    {
        printf("   Zenbaki positiboa eman (datu bakarra): ");
        scanf("%lf", &fZbk);
        if (fZbk <= 0.0)
            printf("   Datua 0.0 baino handiagoa izan dadila\n");
    } while (fZbk <= 0.0);

    fEmaitza = fZbk / 2.0; // lehenengo hurbilketa

    printf("   rEPSILOM = %.9f   rHurbilketa = %.9f\n", rEPSILOM, fEmaitza);
    printf("\n");

    do // Newton-Raphson iterazio metodoa erro karratua kalkulatzeko
    {
        fAurrekoa = fEmaitza;
        fEmaitza = fAurrekoa - (fAurrekoa * fAurrekoa - fZbk) / (2 * fAurrekoa);
        printf("fAurrekoa=%22.16f     fEmaitza=%22.16f\n", fAurrekoa, fEmaitza);
    } while (fabs(fEmaitza - fAurrekoa) > rEPSILOM);

    printf("\n");
    printf("%.4f-ren erro koadroa (Newton-Raphson) %.16f da\n", fZbk, fEmaitza);
    printf("%.4f-ren erro koadroa sqrt() funtzioaz %.16f da\n", fZbk, sqrt(fZbk));

    printf("\n");
    printf("============================\n");
    printf("ENTER tekla sakatu amaitzeko\n");
    printf("============================\n");

    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}



Grafiko interaktiboarekin lan egiteko, sakatu x^3 —27000 funtzioan edo irudiaren gainean

n zenbaki erreal positibo baten erro kubikoa kalkula dezagun. Hona hemen, Newton–Raphson metodotik eratorrren formula:

Konprobazioa egiteko, logaritmoak har daitezke programan:
x3 = n     x = n1/3    log(x) = log(n1/3)    x = exp(log(n1/3))    x = exp(1/3·log(n))

Hona hemen zenbaki baten erro karratua kalkulatzen duen Ariketa-30a_NewtonHurbilketaMetodoa programaren kodea:

/* Ariketa-30b_NewtonMetodoa-ErroKuboa: do-while */
  
//    Newton-Raphson metodoa
//    ----------------------
//    Xi+1 = Xi - f(Xi)/f'(Xi)
//    Xi+1 = Xi - (X¡*Xi - N) / 2*Xi
//    Xi+1 = (N/Xi + Xi) / 2

//    Irteteko baldintza, jarraitu hau betetzean:
//    fabs(Xi+1 - Xi) > fDoitasuna

//    -------

//    Hirugarren graduko parabola
//    x^3 - N = 0  ->  x^3 = N

//    f(x) = x^3 - N
//    f'(x) = 3X^2

//    Newton-Raphson metodoa
//    Xi+1 = Xi - f(Xi)/f'(Xi)
//    Xi+1 = Xi - (Xi^3 - N)/3Xi^2
//    Xi+1 = (N/Xi^2 + 2Xi)/3

//    Kontuz Xi ez dadila zero izan, halakoetan
//    beste datu bat hautatu.

#include <stdio.h>
#include <math.h>  // log() eta exp() funtzioetarako

int main()
{
    double fZbk, fEmaitza, fAurrekoa;

    printf("\n");
    printf("   NEWTON vs. SQRT()\n");
    printf("   Eskuko kalkulagailu balitz bezala lan eginez\n");

    do // zero ez den zenbaki positiboa eskatu erabiltzaileari
    {
        printf("   Zenbaki positiboa eman (datu bakarra): ");
        scanf("%lf", &fZbk);
        if (fZbk <= 0.0)
            printf("   Datua 0.0 baino handiagoa izan dadila\n");
    } while (fZbk <= 0.0);

    fEmaitza = fZbk / 2.0; // lehenengo hurbilketa

    printf("   rEPSILOM = %.9f   rHurbilketa = %.9f\n", rEPSILOM, fEmaitza);
    printf("\n");

    do // Newton-Raphson iterazio metodoa erro karratua kalkulatzeko
    {
        fAurrekoa = fEmaitza;
        fEmaitza = fAurrekoa - (fAurrekoa * fAurrekoa - fZbk) / (2 * fAurrekoa);
        printf("fAurrekoa=%22.16f     fEmaitza=%22.16f\n", fAurrekoa, fEmaitza);
    } while (fabs(fEmaitza - fAurrekoa) > rEPSILOM);

    printf("\n");
    printf("%.4f-ren erro koadroa (Newton-Raphson) %.16f da\n", fZbk, fEmaitza);
    printf("%.4f-ren erro koadroa sqrt() funtzioaz %.16f da\n", fZbk, sqrt(fZbk));

    printf("\n");
    printf("============================\n");
    printf("ENTER tekla sakatu amaitzeko\n");
    printf("============================\n");

    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}






  • Ariketa-30a_NewtonMetodoa-ErroKarratua.cbp | main.c  
  • Ariketa-30b_NewtonMetodoa-ErroKuboa.cbp | main.c  


 

Ariketa 29 | Newton-en metodoa, bigarren graduko edozein parabolarekin

ZER DAKIDAN:
Dagoeneko for, do-while eta while agindu errepikakorra erabili ditut. Baina bakoitza edozein egoeratan erabil baiteke?



ZER IKASIKO DUDAN:
Prozesu errepikorraren iterazio kopurua ezezaguna denean, do-while edo while agindu errepikakorrek erabiliko ditut.


Newton-Raphson hurbilketa-metodoa ax2+bx+c=0 ekuazioaren erro bat kalkulatzeko

Newton–Raphson metodoa (Newton-en metodo gisa ere ezagutzen dena) zenbakizko analisi-metodo bat da. Metodo honek funtzioen erro gero eta hobeak lortzen ditu, hau da, funtzioa zero egiten duen x balioa bilatzen du. Beste modu batez esanik, funtzioak OX ardatza mozten duen balioa (funtzioaren erroa) ematen du Newton–Raphson metodoak. Algoritmoa erroaren hurbilketa batekin hasten da eta urrats bakoitzean erroaren hurbilketa hobea lortzen du.

Matematikan funtzio koadratikoa funtzio polinomiko mota bat da, itxura kanonikoan honela definitua:

ax2 + bx + c = 0

Non a, b eta c zenbaki errealak diren (eta a ≠ 0).

Funtzio koadratikoren deribatua lerro zuzena da eta bere integrala funtzio kubikoa da.



Aldagai bakarreko funtzio errealen kasuan honakoa da metodoa:
Izan bedi ƒ funtzioa x errealentzat definitua, eta izan bedi ƒ' bere deribatua. Erroaren hasierako hurbilketa bat behar dugu, x0. Erroaren hurbilketa horretan oinarrituz hurbilketa hobea izango den x1 honelaxe lortzen da:
Iterazioak eginez, n+1 hurbilketa n hurbilketan oinarritzen da formula honen arabera:
Formula horren zergatia geometrikoki adieraz daiteke. Hurrengo irudiko lerro urdina  f(x) funtzioa da, eta lerro zuzen gorria f(x) funtzioaren tangentea (xn, f(xn)) puntuan:
Berde koloreko distantziari hobekuntza deitzen badiogu, orduan alfa angeluaren tangentea f(xn)/hobekuntza litzateke, baina tangente hori f(x) funtzioaren deribatua (xn, f(xn))puntuan da, lerro zuzen gorriaren malda alfa angeluaren tangentea da. Horregatik:
tag(alfa)= f(xn)/hobekuntza   eta aldi berean   tag(alfa)=malda= f'(xn)
beraz    f'(xn)= f(xn)/hobekuntza     (non  hobekuntza=xn-xn+1)
f'(xn)= f(xn)/(xn-xn+1)    nondik    xn-xn+1= f(xn)/f'(xn)
xn+1 = xn f(xn)/f'(xn)


ax2+bx+c parabolaren erro bat kalkula dezagun Newton–Raphson metodoa aplikatuz non a, b eta c koefizienteak ezagunak diren. Hona hemen, Newton–Raphson metodotik eratorren formula:
xn+1 = xn f(xn)/f'(xn)
a, b eta c ezagunak izanik x lortu:
f(x)=ax2+bx+c
f'(x)=2ax+b

xi+1 = xi f(xi)/f'(xi)
xi+1 = xi - (axi2+bxi+c)/(2axi+b)

Kontu berezia eduki beharko dugu 2axi+b adierazpenaren balioarekin. Ez dugu onartuko zero izatea bestela programa era desegokian bukatuko delako, hots, goiko irudiko tangentea den lerro gorria ezin daiteke horizontala izan (tangente horrek ez luke OX ardatza moztuko).



Demagun a=1, b=-4 eta c=3 koefizienteak dituen parabolaren erroa kalkulatu nahi dugula. Irudian ikus daitekeen bezala x2-4x+3 parabolaren erroak 1 eta 3 dira. Bestalde, irudian ikusten da ere hurbilketa bezala ez dugula x=2 emango, puntu horretan maldak 0 balio duelako eta lerro horizontalak ez duelako OX ardatza mozten eta ondorioz programak abortatzen duelako.


Hurbilketa desberdinen araberako programaren hiru irteera hauek erakusten dira jarraian:

Hasierako hurbilketa 2.0000000001 edo handiagoa bada, emaitza 3.0 izango da

Hasierako hurbilketa 1.9999999999 edo txikiagoa bada, emaitza 1.0 izango da

Hasierako hurbilketa 2.0 bada, algoritmoak huts egingo du

Zer gertatzen da hurbilketa 1.0 eta 3.0 artean badago (2.0 izan gabe, noski). Adibidez, zer gertatzen da hurbilketa 1.5 bada edo 2.5 bada. Kasu bietan emaitzak zuzenak dira, baina lortuko den erroa lehen hurbilketaren araberakoa da izango da:
  • Lehen hurbilketa 1.5 bada, emaitza den erroa 1.0 izango da
  • Lehen hurbilketa 2.5 bada, emaitza den erroa 3.0 izango da
Beraz, ikertzen ari garen x2-4x+3 parabolaren kasuan:
  • Lehen hurbilketa 2.0 baino txikiagoa bada, emaitza den erroa 1.0 izango da
  • Lehen hurbilketa 2.0 baino handiagoa bada, emaitza den erroa 3.0 izango da
  • Lehen hurbilketa 2.0 bada, ezin daiteke Newton–Raphson metodoa aplikatu



Demagun a=1, b=0 eta c=-9 koefizienteak dituen parabolaren erroa kalkulatu nahi dugula. Irudian ikus daitekeen bezala x2-9 parabolaren bi erroak 3 dira. Bestalde, irudian ikusten da ere hurbilketa bezala x=3 emango bagenu, puntu horretan malda 0 izan arren programa ondo ibiliko litzatekeela puntu hori soluzioa delako.

Hurbilketa desberdinen araberako programaren hiru irteera hauek erakusten dira jarraian:

2.1 hasierako hurbilketa 4.0 baino txikiagoa bada, emaitza 4.0 izango da

5.9 hasierako hurbilketa 4.0 baino handiagoa bada, emaitza 4.0 izango da

Hasierako hurbilketa 4.0 bada, iterazio bakarrarekin 4.0 emaitza lortzen da




Lerroa horizontala ezin daitekeela izan arestian aipatu dugu, ikus dezagun orain zer gertatzen den ax2+bx+c parabolak OX ardatza ez duenan mozten ezta ikutzen ere ez.

Gogoratu Ariketa 14 | Bigarren graduko ekuazioa ariketa non Δ diskriminatzailearen arabera bigarren mailako ekuazio batek soluzio desberdinak izan ditzakeela:
  • Δ > 0, diskriminatzailea positiboa bada, bi soluzioak zenbaki erreal dira. Egoera hau aintzakotzat hartzen du aurreko NewtonErroErrealak.exe programak eta arazorik ez da sortzen (baldin eta lerro gorri horizontalik gertatzen ezbada)
  • Δ = 0, diskriminatzailea 0 bada, soluzioa bakarra da eta gainera zenbaki erreala. Egoera hau aintzakotzat hartzen du aurreko NewtonErroErrealak.exe programak eta arazorik ez da sortzen (nahiz eta hurbilketa puntuari dagokion lerro gorria lerro horizontala izan, hurbilketa puntu hori soluzioa baita)
  • Δ < 0, diskriminatzailea negatiboa bada, ez dago erro errealik eta bi soluzioak zenbaki konplexuak dira eta bata bestearen zenbaki konplexu konjugatu dira. Egoera hau ez du aintzakotzat hartzen aurreko NewtonErroErrealak.exe programak eta programaren exekuzioa ez da eteten, hurrengo adibidearen NewtonEdozeinParabola.exe programa  ikusi

Demagun a=1, b=-4 eta c=6 koefizienteak dituen polinomioaren erroa kalkulatu nahi dugula. Irudian ikus daitekeen bezala x2-4x+6 parabolak ez du OX ardatza mozten eta ondorioz erro errealik ez daukala.

x2-4x+6=0 polinomioaren kasuan ez dugu Newton-en metodoa aplikatuko, eta horren ordez bigarren graduko ekuazioaren formula erabiliko dugu:

Programa exekutatzean erro irudikarien kasua erakusten da hemen:

 Irudikariak direnean, hurbilketarik ez eskatu eta Newton-en metodoa ez aplikatu
(erro irudikariak bigarren graduko ekuazioaren formularen bitartez lortzen dira)


Bigarren graduko polinomio baten erro bat kalkulatu Newton–Raphson metodoa aplikatuz, non fA, fB eta fC koefizienteak teklatuz ematen diren eta prozesu errepikakorra gauzatzeko do-while agindua erabiltzen den:

/* Ariketa-29a_NewtonHurbilketaMetodoa: do-while agindua erabiliz */

//    Newton-Raphson metodoa
//    ----------------------
//    Xi+1 = Xi - f(Xi)/f'(Xi)
//    Xi+1 = Xi - (X¡*Xi - N) / 2*Xi
//    Xi+1 = (N/Xi + Xi) / 2

//    Irteteko baldintza:
//    fabs(Xi+1 - Xi) < fDoitasuna

//    -------

//    Bigarren graduko edozein parabola
//    Ax^2 + Bx + C = 0

//    f(x) = Ax^2 + Bx + C
//    f'(x) = 2Ax + B

//    Newton-Raphson metodoa
//    Xi+1 = Xi - f(Xi)/f'(Xi)
//    Xi+1 = Xi - (AXi^2 + BXi + C)/(2AXi + B)

//    Kontuz (2AXi+B) ez dadila zero izan,
//    halakoetan beste hurbilketa bat hautatu.

//    Kontuz parabolak OX ardatza ez duenean mozten ez ikutzen.
//    Halakoetan programaren exekuzioa ez da eteten, horregatik
//    B^2-4AC diskriminatzailea kalkulatu eta negatiboa izanez
//    gero erro irudikariak kalkulatu eta balioak pantailaratu.

#include <stdio.h>   // printf() eta scanf() funtzioetarako
#include <math.h>    // sqrt() funtziorako

#define fEPSILON  0.000000001

int main()
{
    float fA, fB, fC, fEmaitza, fAurrekoa, fDiskriminatzailea;

    printf("\n\n");
    printf("\n Bigarren graduko parabola baten erro bat kalkulatu");
    printf("\n --------------------------------------------------\n");

    printf(" x^2-ren A koefizientea eman (adibidez 1): ");
    scanf("%f", &fA);
    printf(" x-ren B koefizientea sartu (adibidez -4): ");
    scanf("%f", &fB);
    printf(" C koefiziente librea sartu (esaterako 3): ");
    scanf("%f", &fC);

    fDiskriminatzailea = fB*fB - 4*fA*fC;

    if (fDiskriminatzailea >= 0.0)
    {
        do
        {
            printf("\n Erroaren hurbilpen bat eman, x bat eman: ");
            scanf("%f", &fEmaitza);   // lehendabiziko hurbilketa

            printf("\n fEPSILON = %.9f   fHurbilpena = %.9f", fEPSILON, fEmaitza);

            if (2*fA*fEmaitza + fB == 0.0)
            {
                printf("\n Lehen lerroa horizontala da.");
                printf("\n Erroa ezin daiteke kalkulatu,");
                printf("\n beste hurbilpen bat eman.\n");
            }
        } while (2*fA*fEmaitza + fB == 0.0);

        do
        {
            fAurrekoa = fEmaitza;
            fEmaitza = fAurrekoa - (fA*fAurrekoa*fAurrekoa + fB*fAurrekoa + fC) / (2*fA*fAurrekoa + fB);
            printf("\n fAurrekoa = %.16f     fEmaitza = %.16f", fAurrekoa, fEmaitza);
        } while (fabs(fEmaitza - fAurrekoa) > fEPSILON);


        printf("\n %.1fX^2", fA);
        if (fB >= 0)
            printf(" +%.1fX", fB);
        else
            printf(" %.1fX", fB);
        if (fC >= 0)
            printf(" +%.1f = 0  ekuazioaren emaitza %.16f da", fC, fEmaitza);
        else
            printf(" %.1f = 0  ekuazioaren emaitza %.16f da", fC, fEmaitza);
    }
    else   // Diskriminatzailearen if-else
    {
        printf("\n %.1f X^2 + %.1f X + %.1f parabolak ez du OX ardatza mozten", fA, fB, fC);
        printf("\n Erroak irudikariak dira:");
        printf("\n x1 = %.2f X^2 +i(%.2f) eta", -fB/(2*fA), sqrt(-fDiskriminatzailea)/(2*fA));
        printf("\n x2 = %.2f X^2 -i(%.2f)", -fB/(2*fA), sqrt(-fDiskriminatzailea)/(2*fA));
    }

    printf("\n\n");
    return 0;
}


Bigarren graduko polinomio baten erro bat kalkulatu Newton–Raphson metodoa aplikatuz, non fA, fB eta fC koefizienteak teklatuz ematen diren eta prozesu errepikakorra gauzatzeko do-while agindua erabiltzen den:

/* Ariketa-29b_NewtonHurbilketaMetodoa: while agindua erabiliz */

//    Newton-Raphson metodoa
//    ----------------------
//    Xi+1 = Xi - f(Xi)/f'(Xi)
//    Xi+1 = Xi - (X¡*Xi - N) / 2*Xi
//    Xi+1 = (N/Xi + Xi) / 2

//    Irteteko baldintza:
//    fabs(Xi+1 - Xi) < fDoitasuna

//    -------

//    Bigarren graduko edozein parabola
//    Ax^2 + Bx + C = 0

//    f(x) = Ax^2 + Bx + C
//    f'(x) = 2Ax + B

//    Newton-Raphson metodoa
//    Xi+1 = Xi - f(Xi)/f'(Xi)
//    Xi+1 = Xi - (AXi^2 + BXi + C)/(2AXi + B)

//    Kontuz (2AXi+B) ez dadila zero izan,
//    halakoetan beste hurbilketa bat hautatu.

//    Kontuz parabolak OX ardatza ez duenean mozten ez ikutzen.
//    Halakoetan programaren exekuzioa ez da eteten, horregatik
//    B^2-4AC diskriminatzailea kalkulatu eta negatiboa izanez
//    gero erro irudikariak kalkulatu eta balioak pantailaratu.


#include <stdio.h>   // printf() eta scanf() funtzioetarako
#include <math.h>    // sqrt() funtziorako

#define fEPSILON  0.000000001

int main()
{
    float fA, fB, fC, fEmaitza, fAurrekoa, fDiskriminatzailea;

    printf("\n\n");
    printf("\n Bigarren graduko parabola baten erro bat kalkulatu");
    printf("\n --------------------------------------------------\n");

    printf(" x^2-ren A koefizientea eman (adibidez 1): ");
    scanf("%f", &fA);
    printf(" x-ren B koefizientea sartu (adibidez -4): ");
    scanf("%f", &fB);
    printf(" C koefiziente librea sartu (esaterako 3): ");
    scanf("%f", &fC);

    fDiskriminatzailea = fB*fB - 4*fA*fC;

    if (fDiskriminatzailea >= 0.0)
    {
        do
        {
            printf("\n Erroaren hurbilpen bat eman, x bat eman: ");
            scanf("%f", &fAurrekoa);   // lehendabiziko hurbilketa

            printf("\n fEPSILON = %.9f   fHurbilpena = %.9f", fEPSILON, fAurrekoa);

            if (2*fA*fAurrekoa + fB == 0.0)
            {
                printf("\n Lehen lerroa horizontala da.");
                printf("\n Erroa ezin daiteke kalkulatu,");
                printf("\n beste hurbilpen bat eman.\n");
            }
        } while (2*fA*fAurrekoa + fB == 0.0);

        fEmaitza = fAurrekoa - (fA*fAurrekoa*fAurrekoa + fB*fAurrekoa + fC) / (2*fA*fAurrekoa + fB);
        printf("\n fAurrekoa = %.16f     fEmaitza = %.16f  <-- kanpoan", fAurrekoa, fEmaitza);

        while (fabs(fEmaitza - fAurrekoa) > fEPSILON)
        {
            fAurrekoa = fEmaitza;
            fEmaitza = fAurrekoa - (fA*fAurrekoa*fAurrekoa + fB*fAurrekoa + fC) / (2*fA*fAurrekoa + fB);
            printf("\n fAurrekoa = %.16f     fEmaitza = %.16f", fAurrekoa, fEmaitza);
        }

        printf("\n %.1fX^2", fA);
        if (fB >= 0)
            printf(" +%.1fX", fB);
        else
            printf(" %.1fX", fB);
        if (fC >= 0)
            printf(" +%.1f = 0  ekuazioaren emaitza %.16f da", fC, fEmaitza);
        else
            printf(" %.1f = 0  ekuazioaren emaitza %.16f da", fC, fEmaitza);
    }
    else   // Diskriminatzailearen if-else
    {
        printf("\n %.1f X^2 + %.1f X + %.1f parabolak ez du OX ardatza mozten", fA, fB, fC);
        printf("\n Erroak irudikariak dira:");
        printf("\n x1 = %.2f X^2 +i(%.2f) eta", -fB/(2*fA), sqrt(-fDiskriminatzailea)/(2*fA));
        printf("\n x2 = %.2f X^2 -i(%.2f)", -fB/(2*fA), sqrt(-fDiskriminatzailea)/(2*fA));
    }

    printf("\n\n");
    return 0;
}



Ondoko Irudiaren gainean klik egin x3-3x funtzioa aztertzeko:

Ax3+Cx=0 itxurako hirugarren graduko polinomio baten erro bat kalkulatu Newton–Raphson metodoa aplikatuz, non fB eta fD koefizienteak 0.0 diren, eta fA teklatuz ematen den balio positiboa den, eta fC teklatuz ematen den balio negatiboa den:

/* Ariketa-29c1_HirugarrenGradukoPolinomioBat: do-while agindua erabiliz */

//    Newton-Raphson metodoa
//    ----------------------
//    Xi+1 = Xi - f(Xi)/f'(Xi)
//    Xi+1 = Xi - (X¡*Xi - N) / 2*Xi
//    Xi+1 = (N/Xi + Xi) / 2

//    Irteteko baldintza:
//    fabs(Xi+1 - Xi) < fDoitasuna

//    -------

//    Hirugarren graduko itxura hau duen polinomioa:
//    Ax^3 + Bx^2 + Cx + D = 0
//    Non:  # A positiboa
//          # B zero
//          # C negatiboa
//          # D zero

//    f(x) = Ax^3 + Cx
//    f'(x) = 3Ax^2 + C

//    Newton-Raphson metodoa
//    Xi+1 = Xi - f(Xi)/f'(Xi)
//    Xi+1 = Xi - (AXi^3 + CXi)/(3AXi^2 + C)

//    Kontuz (3AXi^2+C) ez dadila zero izan,

#include <stdio.h>   // printf() eta scanf() funtzioetarako
#include <math.h>    // sqrt() funtziorako

#define fEPSILON  0.000000001

int main()
{
    float fA, fC, fEmaitza, fAurrekoa;
    int iMoztu;  // lerro horizontala denean iMoztu=0 bestela iMoztu=0

    printf("\n\n");
    printf("\n Hirugarren graduko 1x^3-3x=0 polinomioaren erro bat kalkulatu");
    printf("\n -----------------------------=-------------------------------\n");

    do
    {
        printf(" x^3-ren A koefiziente positiboa eman (adibidez 1): ");
        scanf("%f", &fA);
    } while (fA <= 0.0);

    do
    {
        printf(" x-ren C koefiziente negatiboa sartu (adibidez -3): ");
        scanf("%f", &fC);
    } while (fC >= 0.0);

    do
    {
        printf("\n Erroaren hurbilpen bat eman, x bat eman: ");
        scanf("%f", &fEmaitza);   // lehendabiziko hurbilketa, edozein izan daiteke
        if (0.0 == 3*fA*fEmaitza*fEmaitza + fC)
            printf(" Lehen lerroa horizontala da, beste hurbilpen batekin saiatu...\n");
    } while (0.0 == 3*fA*fEmaitza*fEmaitza + fC);

    printf("\n fEPSILON = %.9f   fHurbilpena = %.9f", fEPSILON, fEmaitza);
    iMoztu = 0;
    do
    {
        fAurrekoa = fEmaitza;
        if (3*fA*fAurrekoa*fAurrekoa + fC == 0.0)   // lerroa horizontala bada errepikatze prozesua moztu
            iMoztu = 1;
        else
            fEmaitza = fAurrekoa - (fA*fAurrekoa*fAurrekoa*fAurrekoa + fC*fAurrekoa) / (3*fA*fAurrekoa*fAurrekoa + fC);
        printf("\n fAurrekoa = %.16f     fEmaitza = %.16f", fAurrekoa, fEmaitza);
    } while ((fabs(fEmaitza - fAurrekoa) > fEPSILON) && (iMoztu == 0));


    if (iMoztu == 1)   // lerroa horizontalik atera bada, mezua eta amaitu
    {
        printf("\n Lerro horizontala atera da.");
        printf("\n Erroa ezin daiteke kalkulatu,");
        printf("\n hurbilpen berriarekin saiatu.");
    }
    else
    {
        printf("\n %.1fX^3 %.1fX = 0 ekuazioaren emaitzaren bat %.16f da", fA, fC, fEmaitza);
    }

    printf("\n\n");
    return 0;
}

Ariketa-29c2_HirugarrenGradukoPolinomioBat.cbp proiektuan kalkulu bera egiten da baina prozesu errepikakora gauzatzeko while agindua erabiltzen da.







  • Ariketa-29a_NewtonHurbilketaMetodoa.cbp | main.c         [do-while]
  • Ariketa-29b_NewtonHurbilketaMetodoa.cbp | main.c         [while]
  • Ariketa-29c1_NewtonHurbilketaMetodoa.cbp | main.c       [do-while]
  • Ariketa-29c2_NewtonHurbilketaMetodoa.cbp | main.c       [while]