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


iruzkinik ez:
Argitaratu iruzkina