Rekurentní vztahy

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
//#include <limits.h>
 
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
 
double *epsilon=NULL;
double *x=NULL;
 
double druhaodmocnina(double neznama, double eps) {
  //Y0 = X   // po�åte�ní aproximace
  //Yi+1 = 0.5 * (X/Yi + Yi)
  double y=neznama;
  if (y==0) return 0;
  double last=0;
  if (neznama>0) {
    do {
      last=y;
      y=(neznama/last+last)/2;
    } while (fabs(y-last)>=eps);
  } else {
    fprintf(stderr,"Odmocninu lze vypocitat jen z kladnych cisel!\n");
    return NAN;
  }
  //printf("%.10le\n",sqrt(*x));
  return y;
}
 
double sinus(double neznama, double eps) {
  //sin(X) = X - X3/3! + X5/5! - X7/7! + ...
  short neg=0;
  if (neznama<0) { //pokud je zaporny, udelame ho kladny
    neznama=fabs(neznama);
    neg++;
  }
  if (neznama>IZP_2PI) neznama=fmod(fabs(neznama),IZP_2PI); //poladime konvergenci
//  printf("%.10le\n",neznama);
  double neznama2=pow(neznama,2);
  double y=neznama;
  double prirustek=neznama;
  unsigned short k=3;
  while (fabs(prirustek)>=eps) {
    prirustek=(-prirustek/(k*(k-1)))*neznama2;
    k+=2;
    y+=prirustek;
  }
  if (neg!=0) y*=-1; //kdyz byl vstup zapornej, tak se musi "uzapornit" i vystup
//  printf("%.10le\n",sin(*x));
  if (y>1 || y<-1) {
    fprintf(stderr,"Vysledek je mimo rozsah <-1;1>!\n");
    return NAN;
  }
  return y;
}
 
double kosinus(double neznama, double eps) {
 return (sinus((IZP_PI_2-neznama), eps));
}
 
double tangens(double neznama, double eps) {
  //printf("%.10le\n",tan(*x));
  double y=sinus(neznama,eps)/kosinus(neznama,eps);
  if (y==INFINITY) {
    fprintf(stderr,"Funkce tangens neni pro tuto hodnotu definovana!\n");
    return NAN;
  }
  return y;
}
 
double kotangens(double neznama, double eps) {
  //printf("%.10le\n",tan(*x));
  double y=kosinus(neznama,eps)/sinus(neznama,eps);
  if (y==INFINITY) {
    fprintf(stderr,"Funkce kotangens neni pro tuto hodnotu definovana!\n");
    return NAN;
  }
  return y;
}
 
double enax(double neznama, double eps) {
  //eX = 1 + X + X2/2! + X3/3! + ...
  short neg=0;
  if (neznama<0) {
    neznama=fabs(neznama);
    neg=1;
  }
  double y=neznama+1;
  double prirustek=neznama;
  unsigned short k=2;
  while (fabs(prirustek)>=eps && y!=INFINITY && prirustek!=INFINITY) {
    prirustek*=(neznama/k);
    k++;
    y+=prirustek;
  }
  if (y==INFINITY || prirustek==INFINITY) {
    fprintf(stderr,"Preteceni!\n");
    return NAN;
  }
  if (neg!=0) y=1/y;
  //printf("%.10le\n",exp(*x));
  return y;
}
 
double prirozenylogaritmus(double neznama, double eps) {
  if (neznama==0) return -INFINITY;
  if (neznama<0){
   fprintf(stderr,"Prirozeny logaritmus lze pocitat jen z cisel vetsich nez 0!\n");
   return NAN;
  }
  int mocnina=0;
  while (neznama>=2) { //priblizit se 1
    neznama=neznama/10;
    mocnina++;
  }
  while (neznama<=.1 && neznama>0) { //priblizit se 1
    neznama=neznama*10;
    mocnina--;
  }
  double z=(neznama-1)/(neznama+1);
  double zz=z*2;
  double z2=pow(z,2);
  double y=zz;
  unsigned int k=1;
  double prirustek=y;
  while (fabs(prirustek)>=eps && prirustek!=INFINITY && y!=INFINITY) {
    prirustek*=((k*z2)/(k+2));
//    printf ("%f\n",prirustek);
    k+=2;
    y+=prirustek;
  }
  if (mocnina!=0) y+=(mocnina*log(10)); //pokud se musela doladit konvergence (snad nevadi pouziti fce log())
  return y;
}
 
double odmocninazenax(double neznama, double eps) {
  double y=druhaodmocnina(enax(neznama,eps),eps);
  return y;
}
 
double sinusprirozenehologaritmu(double neznama, double eps) {
  double y=sinus(prirozenylogaritmus(neznama,eps),eps);
//  printf("%.10le\n",sin(log(neznama)));
  return y;
}
 
void napoveda(void) {
  printf("Pouziti: program -FUNKCE EPSILON\nDale zadavejte vstupy pro zvolenou funkci.\n\nFUNKCE:\nsqrt    druha odmocnina\nsin     sinus\ncos     kosinus (bonus)\ntan     tangens (bonus)\ncot     kotangens (bonus)\nex      mocnina Eulerova cisla\nln      prirozeny logaritmus\nsqrtex  druha odmocnina z mocniny Eulerova cisla\nsinln   sinus z prirozeneho logaritmu\n\nEPSILON:\nPresnost vypoctu. Musi byt vetsi nez 0. Cim blize 0, tim presnejsi vypocet.\n\nSepsal a v hlavni rohli sehral xkalab00.\n");
}
 
int main(int argc, char *argv[]) {
  if (argc == 1 || (argc == 2 && strcmp("-h", argv[1]) == 0)) {
    napoveda();
    return EXIT_SUCCESS;
  }
 
  if (argc == 3) { //nacteme vstupy
    epsilon=malloc(sizeof (double));
    *epsilon=atof(argv[2]); //nacteme epsilon
    if (*epsilon<=0) {
      fprintf(stderr,"Spatne epsilon!\n");
      free(epsilon);
      return EXIT_FAILURE;
    }
  } else {
    fprintf(stderr,"Spatne parametry!\n");
    return EXIT_FAILURE;
  }
 
  x=malloc(sizeof (double));
  int a=scanf("%lf", x); //nactem vstup
  while (a!=EOF) { //pokud je v poradku pokracujem
    if (a!=1) { //pokus se nic nenacetlo
      fprintf(stderr,"To nebylo cislo!\n");
      scanf("%*s");
      a=scanf("%lf",x);
      continue;
    }
 
    //sqrt
    if (strcmp("-sqrt", argv[1])==0) {
      double y=druhaodmocnina(*x, *epsilon);
      if (isnan(y)==0) printf("%.10le\n",y);
    }
 
    //sin
    if (strcmp("-sin", argv[1])==0) {
      double y=sinus(*x, *epsilon);
      if (isnan(y)==0) printf("%.10le\n",y);
    }
 
    //cos (kdyz uz to umi sinus...)
    if (strcmp("-cos", argv[1])==0) printf("%.10le\n",kosinus(*x,*epsilon));
 
    //tan
    if (strcmp("-tan", argv[1])==0) {
      double y=tangens(*x, *epsilon);
      if (isnan(y)==0) printf("%.10le\n",y);
    }
 
    //cot
    if (strcmp("-cot", argv[1])==0) {
      double y=kotangens(*x, *epsilon);
      if (isnan(y)==0) printf("%.10le\n",y);
    }
 
    //exp
    if (strcmp("-ex", argv[1])==0) {
      double y=enax(*x, *epsilon);
      if (isnan(y)==0) printf("%.10le\n",y);
    }
 
    //log
    if (strcmp("-ln", argv[1])==0) {
      double y=prirozenylogaritmus(*x, *epsilon);
      if (isnan(y)==0) printf("%.10le\n",y);
    }
 
    //sqrt(ex)
    if (strcmp("-sqrtex", argv[1])==0) printf("%.10le\n",odmocninazenax(*x, *epsilon));
 
    //sin(ln)
    if (strcmp("-sinln", argv[1])==0) {
      printf("%.10le\n",sinusprirozenehologaritmu(*x, *epsilon));
    }
 
    a=scanf("%lf", x);
  }
  free(epsilon);
  free(x);
  return EXIT_SUCCESS;
}
//gcc -std=c99 -Wall -W -lm -pedantic proj2.c -o proj2 -O2