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 kopurua9balitz, bere irteera 0, 1, 1, 2, 3, 5, 8, 13, 21, izango litzateke.
Hauxe da Fibonacciren segidaren adierazpen orokorra:
Fibonacci-ren sekuentziako bi zenbaki hartuz eta zatiketa eginez, urrezko zenbakia edo jainkozko proportzioa edo urrezko proportzioa edo zerutiar zenbakia lortzen da:
Goiko azalpenean egiten den bezala, Fibonacci zenbakien iZenbat kopurua teklatuz irakurri eta for egitura erabiliz ondoko taula pantailaratu, programan errepikatzen den prozesua hauxe dela:
Datua15izanik 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:
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:
Datua20izanik 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:
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 bitartezNzenbaki 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:
/* 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;
}
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 batukariafAzkenEmaitzada eta aurreko iterazioan batukariafAurrekoEmaitzada, balio bien arteko diferentzia txikia izatean (adibidez0.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;
}
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)
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)
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+badierazpenaren 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 hurbilketa2.0000000001edo handiagoa bada, emaitza3.0izango da
Hasierako hurbilketa1.9999999999edo txikiagoa bada, emaitza1.0izango da
Hasierako hurbilketa2.0bada, 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.1hasierako hurbilketa4.0baino txikiagoa bada, emaitza4.0izango da
5.9hasierako hurbilketa4.0baino handiagoa bada, emaitza4.0izango da
Hasierako hurbilketa4.0bada, iterazio bakarrarekin4.0emaitza 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.