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
|
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:
- Erabiliko den fDoikuntza prezisioa teklatuz irakurri (edo konstante ezagun bat izan dadila)
- Lehenego koadranteko fAng angelua graduetan, teklatuz irakurri
- Lehenego koadranteko fAng angelua radianetara igaro fX lortuz
- fX angeluari dagokion fKos kosinua lortu Taylor bitartez (azken batugaia fDoikuntza baino txikiagoa)
- 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; }
- Kosinuaren balioa, eta horrez gain
- Zenbat iteraziotan lortu den kalkulatzea
void KosinuaKalkulatu(float fX, float *fKosinua, int *iIterazioKopurua);
Sarrera: rX angelua radianetan (gogoratu bertsio honetan doikuntza konstante bat dela)Irteera: fKosinua kosinuaren kalkuluaIrteera: 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; }
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 bitartezIrteera: 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 bitartezIrteera: 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; }
|
iruzkinik ez:
Argitaratu iruzkina