/*
Heronverfahren
copyright (C) Robert Nitsch, 2006

Dies ist eine einfache Implementierung des Heronverfahrens (auch bekannt als babylonisches Wurzelziehen).
Der Funktion kann u.a. auch die Genauigkeit übergeben werden (= Anzahl der Iterationen).

Weitere Informationen zum Heronverfahren:
http://de.wikipedia.org/wiki/Babylonisches_Wurzelziehen
*/

#include <iostream>                                                
#include <iomanip>
#include <stdexcept>

using namespace std;

// Debugmodus?
//#define debug


// Deklarationen
long double heronWurzel(double radikand, int genauigkeit=10);
double durchschnitt(double zahl1, double zahl2);
void pause();


int main()
{
	int radikand=-1;
	int genauigkeit=0;
	long double wurzel=0.0;
    
	while(radikand<0)
	{
		cout << "Geben Sie den Radikand ein: " << endl;
		cin >> radikand;
		if(radikand<0) cout << "Der Radikand darf nicht kleiner 0 sein!" << endl << endl;
	}
	cout << "Geben Sie die Genauigkeit der Berechnung an (Anzahl der Iterationen): " << endl;
	cin >> genauigkeit;
    
	// Genauigkeit muss größer 0 sein
	if(genauigkeit <= 0)
	{
		cout << "Genauigkeit muss größer 0 sein! Genauigkeit hat nun den Standardwert 15." << endl << endl;
		genauigkeit=15;
	}
	
	// die Wurzel berechnen
	try
	{
		wurzel=heronWurzel(radikand, genauigkeit);
	}
	catch(...)
	{
		cerr << "Ein unerwarteter Fehler ist aufgetreten. Das Programm wird beendet.";
		pause();
		return 0;
	}
	
	// Ergebnis ausgeben
	cout << "Ergebnis: " << wurzel << endl;
	cout << "Quadrat es Ergebnisses: " << (wurzel * wurzel);
	
	// auf Eingabe warten
	pause();
	
	// programm beenden
	return 0;   
}


// Pause
void pause()
{
	cin.get();
	cin.get();
}


// Funktionen/Methoden
long double heronWurzel(double radikand, int genauigkeit)
{
	// die genauigkeit muss größer 0 sein
	if(genauigkeit<1) return 0;
	
	// als Startwert für die Iteration wird die Hälfte des Radikanden genommen
	long double wurzel=durchschnitt(0,radikand);
	for(int i=0; i<genauigkeit; i++)
	{
			// Iterationsformel
			wurzel=(wurzel+(radikand/wurzel))/2;
				
	
			#ifdef debug
			cout << i << "/" << genauigkeit << ": " << wurzel << endl;
			pause();
			#endif
	}
	
	return wurzel;
}


double durchschnitt(double zahl1, double zahl2)
{
	return (zahl1+zahl2) / 2;
}