/*
description:
	maschinengenauigkeit...
	fuer genaue aufgabenstellung siehe aufgabenblatt 1, aufgabe 1
author:
	seth (www.bierdatenbank.de)
tab stops:
	2 (otherwise hardly readable!)
*/

#include <iostream.h>
#include <math.h>
#include <float.h>
#include <stdio.h>
#include <string.h>
/* #include "/usr/segment/include/MathPlot.h" */

void aufgabe1(){
	double x_0=1.3e-8;
	double zaehler=1-cos(x_0);
	double nenner=pow(x_0,2);
	double ergebnis=(pow(x_0,2)>0)?(1-cos(x_0))/pow(x_0,2):(1-cos(x_0))/DBL_EPSILON;
	cout <<"1.aufg:\n";
	cout <<"=======\n";
	cout <<" a)\n";
	cout <<"  zaehler von f(x_0)= "<< zaehler<<"\n";
	cout <<"  nenner von f(x_0) = "<< nenner<<"\n";
	cout <<"  fl(f(x_0))        = "<< ergebnis<<"\n\n";
	cout <<" b)\n";
	cout <<"  f(x)\\geq 0 => f(x)=|f(x)|\n";
	cout <<"  f(x)=\\frac{1-\\cos(x)}{x^2}\n";
	cout <<"      =\\frac{1+\\sin^2(x/2)-\\cos^2(x/2)}{x^2}\n";
	cout <<"      =\\frac{2\\sin^2(x/2)}{x^2}\n";
	cout <<"      =\\frac{1}{2}\\frac{\\sin^2(x/2)}{(x/2)^2}\n";
	cout <<"      \\leq \\frac{1}{2} = 0.5 < "<<ergebnis<<"\n\n";
	cout <<" c)\n";
	cout <<"  maschinengenauigkeit: "<<DBL_EPSILON<<"\n";
	cout <<"  ersetze zaehler(f(x))=1-cos(x) durch 2*sin^2(x/2)\n";
	cout <<"  neuer zaehler(f(x_0))= "<<2*pow(sin(x_0/2),2)<<"\n";
	cout <<"  neue wert f(x_0)     = "<<((pow(x_0,2)>0)?(2*pow(sin(x_0/2),2))/pow(x_0,2):(2*pow(sin(x_0/2),2))/DBL_EPSILON)<<"\n\n";
}

void aufgabe2(){
	cout <<"2.aufg:\n";
	cout <<"=======\n";
	cout <<" a)\n";
	double ergebnis;
	for(int i=1;i<=15;i++){
		cout <<"  a_{10^"<<((i<10)?"0":"")<<i<<"}: ";
		ergebnis=pow(1+pow(10,-i),pow(10,i));
		printf("%.4f", ergebnis);
		cout <<" mit E_rel=";
		printf("%.4f", fabs(exp(1)-ergebnis)/exp(1));
		cout <<"\n";
	}
	cout <<"\n";
}

void aufgabe3(){
	cout <<"3.aufg:\n";
	cout <<"=======\n";
	cout <<" a)\n";
	double x_i, ergebnis, zaehler, nenner;
	for(int i=1;i<=16;i++){
		cout <<"  fl(g(10^-"<<((i<10)?"0":"")<<i<<"))=";
		x_i=pow(10,-i);
		zaehler=exp(x_i)-1;
		nenner=x_i;
		ergebnis=(x_i==0)?1:(exp(x_i)-1)/x_i;
		printf("%.10f", ergebnis);
		cout <<" mit zaehler=";
		printf("%.20f", zaehler);
		cout <<", nenner=";
		printf("%.20f", nenner);
		cout <<"\n";
	}
	cout <<"\n";
	cout <<" b)\n";
	double y_i;
	for(int i=1;i<=16;i++){
		cout <<"  fl(g(10^-"<<((i<10)?"0":"")<<i<<"))=";
		x_i=pow(10,-i);
		y_i=exp(x_i);
		zaehler=y_i-1;
		nenner=(y_i>0)?log(y_i):-1.0/DBL_EPSILON;
		ergebnis=(y_i>0)?(y_i==1)?1:(y_i-1)/log(y_i):(y_i-1)*(-DBL_EPSILON); // wer durch null teilen will, wird erschossen!
		printf("%.10f", ergebnis);
		cout <<" mit zaehler=";
		printf("%.20f", zaehler);
		cout <<", nenner=";
		printf("%.20f", nenner);
		cout <<"\n";
	}
	cout <<"\n";
	cout <<" c)\n";
	cout <<"  wenn man sich viele nachkommastellen anschaut, sieht man's besser:\n";
	cout <<"  nenner = zaehler bei sehr kleinen werten in b) => fkt.werte=1:\n";
	cout <<"  in a) nicht!\n\n";
}

int signifikanteStellen(double a, double b){
  double komma=0;
	int res=0;
	char buffer_a [50];
	char buffer_b [50];
  int len=sprintf(buffer_a, "%.20f", a);
  sprintf(buffer_b, "%.20f", b);
  while(res<len && buffer_a[res]==buffer_b[res]){
  	res++;
  	if(buffer_a[res]!='.') komma=-1;
 	}
  return (res+komma);
}

void aufgabe4_ausgabe(int schritte, double sum, double actualSum){
	cout <<"  abbruch nach "<<schritte<<" schritten:\n";
	cout <<"  berechnete summe= ";
	printf("%.16f", sum);
	cout <<"\n  differenz       = ";
	printf("%.16f", actualSum-sum);
	cout <<"\n  signifikante stellen: "<<signifikanteStellen(actualSum, sum)<<"\n\n";
}

void aufgabe4(){
	cout <<"4.aufg:\n";
	cout <<"=======\n";
	double pi=3.1415926535897932384626433832795;
	double actualSum=pow(pi,2)/6;
	cout <<"richtige summe    = ";
	printf("%.16f", actualSum);
	cout <<"\n a)\n";
	double a_k, sum=0, sum_old=-1;
	int k=0;
	while(sum-sum_old!=0){
		k++;
		a_k=1/pow(k,2); // k>0 gilt immer
		sum_old=sum;
		sum+=a_k; // ein wenig besser waer wohl s_n+=pow(k,-2);
	}
	aufgabe4_ausgabe(k, sum, actualSum);
	cout <<" b)\n";
	double s=0, e=0, y, temp, tol=1.e-5;
	int n=0;
	while(fabs(actualSum-s)>=tol){
		n++;
		temp=s;
		y=1/pow(n,2)+e; // n>0 gilt immer
		s=temp+y;
		e=(temp-s)+y;
	}
	aufgabe4_ausgabe(n, s, actualSum);
	cout <<" c)\n";
	s=0;
	n=0;
	double mu=0;
	while(fabs(actualSum-s)>=tol){
		n++;
		y=1/pow(n,2); // n>0 gilt immer
		s+=y;
		mu+=fabs(s)+fabs(y);
	}
	cout <<"  berechnete fehlerschranke: "<<pow(mu,2)<<"\n";
	aufgabe4_ausgabe(n, s, actualSum);
}

int main(){
	cout <<endl;
	aufgabe1();
	aufgabe2();
	aufgabe3();
	aufgabe4();
	cout <<endl;
	return 0;
}

