/** * Soubor: main.c * Datum: 04.11.2008 * Autor: Vojtech Kalcik, xkalci01@stud.fit.vutbr.cz * Projekt: Iteracni vypocty, projekt c. 2 pro predmet IZP * Popis: Program provadi v první casti aproximaci funkce tan(x) a ln(x), * v druhe casti vypocet polohy a zrychlení objektu v prostoru na zaklade informaci z radaru. */ #include #include #include #include #include /** * Matematické konstatnty */ const double IZP_E = 2.7182818284590452354; // e const double IZP_PI = 3.14159265358979323846; // pi const double IZP_2PI = 6.28318530717958647692; // 2*pi const double IZP_PI_2 = 1.57079632679489661923; // pi/2 const double IZP_PI_4 = 0.78539816339744830962; // pi/4 const double T = 0.5; // cas radaru const double T_NA_2 = 0.25; // cas radaru na druhou const int LN_E = 1; // prirozeny logaritmus z e const double LN_2 = 0.69314718055994528623; // prirozeny logaritmus z 2 const int POCET_SOURADNIC = 3; // pocet souradnic pro radary /** * Vycet stavu programu. */ enum e_stav { ST_OK = 0, // Vse v poradku ST_NAPOVEDA, // Napoveda ST_MALO_P, // Malo parametru ST_SP_P1, // 1. parametr je spatny ST_SP_P2, // 2. parametr je spatny }; /** * Hlášky programu, které se váží k stavům programu. */ const char *STAVY[] = { "Vse v poradku.", "Autor: Vojtech Kalcik, xkalci01@stud.fit.vutbr.cz\n" "Projekt: Iteracni vypocty, projekt c. 2 pro predmet IZP\n" "Popis: Program provadi v prvni casti aproximaci funkce tan(x) a ln(x)," "v druhe casti vypocet polohy a zrychleni objektu v prostotu na zaklade informaci z radaru.\n" "\n" "Parametry:\n" " -tan eps : vypocet funkce tangens na presnost eps.\n" " -ln eps : vypocet prirozeneho logaritmu na presnost eps.\n" " -radar1 : vypocet polohy objektu v 3D prostoru podle zrychleni.\n" " -radar2 : vypocet zrychleni objektu v 3D prostoru na zaklade polohy.\n" " -h : vypise napovedu.\n" "\n" "eps je cislo typu double vetsi nez 0. Program cte cisla ze standartniho vstupu a hned vypisuje jejich hodnotu. " "U funkci tan a ln jsou cisla na vstupu hodnota x. U radaru1 to je zrychleni objektu v konkretnim case a " "u radaru2 to je aktualni poloha objektu.", "Malo parametru", "Prvni parametr je spatny", "Druhy parametr je spatny", }; /** * Vycet uloh, které muze program provadet */ enum e_co_delat { TAN = 0, // Pocitani tangens. SIN, // Pocitani sinus. COS, // Pocitani kosinus. LN, // Pocitani přirozeného logaritmu. RADAR1, // Pocitani radaru1 RADAR2, // Pocitani radaru2 }; /** * Struktura, kterou navrací funkce zpracuj_parametry. */ typedef struct parametry { int co_delat; double epsilon; int stav; }Tparametry; /** * Struktura, kterou navrací funkce zpracuj_parametry. */ typedef struct polo_ha { double s; double v0; }Tpoloha; /** * Spocita rozvoj pro sinus a cosinus */ double rozvoj_tan(int co_delat, double x, double epsilon) { double clen = 0; double clen_predesly = 0; double vysledek = 0; double co_nasobit = x * x; int cislo = 1; bool prvni = true; if(co_delat == SIN) { clen = x; cislo = 3; } else if(co_delat == COS) { clen = 1; cislo = 2; } vysledek = clen; while((fabs(clen - clen_predesly) > epsilon)||(prvni)) { prvni = false; clen_predesly = clen; clen = -clen * co_nasobit / ((cislo - 1) * cislo); vysledek = vysledek + clen; cislo += 2; } return vysledek; } /** * Spocita rozvoj pro prirozeny logaritmus */ double rozvoj_ln(double x, double epsilon) { double clen = 0; double clen_predesly = 0; double vysledek = 0; double x_min_1 = x - 1; unsigned int cislo = 1; bool prvni = true; double test; cislo = 1; clen = x_min_1; vysledek = clen; while((prvni)||(fabs((clen/cislo) - (clen_predesly/(cislo - 1))) > epsilon)) { prvni = false; clen_predesly = clen; clen = -clen * x_min_1; if(cislo % 10000 == 0) { test = fabs((clen/cislo) - (clen_predesly/(cislo - 1))); } cislo++; vysledek = vysledek + clen / cislo; } return vysledek; } /** * Najde x ze zadaného intervalu, jehoz hodnota odpovida danemu x */ double najdi_x(double zacatek, double rozsah, double x) { double k; double novy_x; k = floor((x-zacatek)/rozsah); novy_x = x - k * rozsah; return novy_x; } /** * Spocita tangens */ double tangens(double x, double epsilon) { double sin_x, cos_x, tan_x; bool vzorecek = false; epsilon = epsilon * 0.1; //kvuli zvetseni chybe pri deleni dvou cisel while((x<-IZP_PI_2)||(x>IZP_PI_2)) { x = najdi_x(-IZP_PI_2, IZP_PI, x); } vzorecek = fabs(x) > IZP_PI_4; if(vzorecek) { epsilon = epsilon * 0.1; x /= 2; } sin_x = rozvoj_tan(SIN, x, epsilon); cos_x = rozvoj_tan(COS, x, epsilon); tan_x = sin_x / cos_x; if(vzorecek) { tan_x = 2 * tan_x / (1 - tan_x * tan_x); } return tan_x; } /** * Spocita prirozeny logaritmus */ double logaritmus(double x, double epsilon) { double ln_x; int pocet_2=0; int pocet_1_2=0; while(x<=1) // tahle zavorka driv, aby pri hodnote x = 1 se pocital rozvoj pro 1 { x *= 2; pocet_1_2++; } while(x>=2) { x /= 2; pocet_2++; } ln_x = rozvoj_ln(x, epsilon) + pocet_2 * LN_2 - pocet_1_2 * LN_2; return ln_x; } /** * Spocita polohu nebo zrychleni podle promenne co_delat */ double radar(int co_delat, double vstup, int souradnice, Tpoloha *poloha) { double s, s0, a, vystup; s0 = poloha[souradnice].s; if(co_delat == RADAR1) { a = vstup; s = s0 + poloha[souradnice].v0 * T + (double)1/2 * a * T_NA_2; vystup = s; } else if(co_delat == RADAR2) { s = vstup; a = 2 * (s - s0 - poloha[souradnice].v0 * T)/T_NA_2; vystup = a; } poloha[souradnice].s = s; poloha[souradnice].v0 = poloha[souradnice].v0 + a * T; return vystup; } /** * Vypsani chybove hlasky nebo napovedy. */ void vypis_hlasku(int stav) { FILE *vystup = stdout; if(stav > ST_NAPOVEDA) { vystup = stderr; } fprintf(vystup, "%s\n", STAVY[stav]); } /** * Cte cisla ze vstupu. */ void cti(Tparametry *parametry) { int je_double; double vysledek; double x = 0; Tpoloha poloha[POCET_SOURADNIC]; int souradnice = 0; for(int i = 0; i < POCET_SOURADNIC; i++) { poloha[i].s = 0; poloha[i].v0 = 0; } while((je_double = scanf("%lf", &x)) != EOF) { if((parametry->co_delat == RADAR1)||(parametry->co_delat == RADAR2)) { if(je_double == 0) { x = NAN; scanf("%*s"); } vysledek = radar(parametry->co_delat, x, souradnice, poloha); souradnice++; if (souradnice == POCET_SOURADNIC) { souradnice = 0; } printf("%.10le\n", vysledek); } else if(je_double != 0) { // funkce tangens if(parametry->co_delat == TAN) { vysledek = tangens(x, parametry->epsilon); } else if(parametry->co_delat == LN) { if(x > 0) { vysledek = logaritmus(x, parametry->epsilon); } else if(x == 0) { vysledek = -INFINITY; } else { vysledek = NAN; } } //printf("%lf - moje: %.10le - knihovna: %.10le odchylka: %lf\n",x , vysledek, tan(x), tan(x) - vysledek); //printf("%lf - moje: %.10le - knihovna: %.10le odchylka: %lf\n",x , vysledek, log(x), log(x) - vysledek); printf("%.10le\n", vysledek); } else { printf("%.10le\n", NAN); scanf("%*s"); } } } /** * Zpracovani parametru */ Tparametry zpracuj_parametry(int argc, char *argv[]) { Tparametry navrat = { .epsilon = 0, .stav = ST_OK, }; if (argc >= 3) { if((strcmp(argv[1], "-tan") == 0)||(strcmp(argv[1], "-ln") == 0)) { if((sscanf(argv[2], "%lf", &navrat.epsilon) == 0)||(navrat.epsilon <= 0)) { navrat.stav = ST_SP_P2; } if(strcmp(argv[1], "-tan") == 0) { navrat.co_delat = TAN; } else { navrat.co_delat = LN; } } else { navrat.stav = ST_SP_P1; } } else if (argc >= 2) { if(strcmp(argv[1], "-h") == 0) { navrat.stav = ST_NAPOVEDA; } else if(strcmp(argv[1], "-radar1") == 0) { navrat.co_delat = RADAR1; } else if(strcmp(argv[1], "-radar2") == 0) { navrat.co_delat = RADAR2; } else if((strcmp(argv[1], "-tan") == 0)||(strcmp(argv[1], "-ln") == 0)) { navrat.stav = ST_MALO_P; } else { navrat.stav = ST_SP_P1; } } else { navrat.stav = ST_MALO_P; } return navrat; } /** *Hlavni program */ int main(int argc, char *argv[]) { Tparametry parametry = zpracuj_parametry(argc, argv); if(parametry.stav == ST_OK) { cti(¶metry); return EXIT_SUCCESS; } else { vypis_hlasku(parametry.stav); if(parametry.stav == ST_NAPOVEDA) { return EXIT_SUCCESS; } else { return EXIT_FAILURE; } } }