/**
 * 
 */
package assertion1;

/**
 * Diese Klasse repraesentiert einen Bruch. Ein Bruch kann aus einer Gleitkommazahl erstellt werden.
 * @author Ralf Kunze (rkunze@uos.de), Institut fuer Informatik, Universitaet
 *         Osnabrueck
 * @date 19.04.2007
 */
public class Bruch {
	private int zaehler;

	private int nenner;

	/**
	 * Custom Constructor, der aus einer Gleitkommazahl einen Bruch ermittelt.
	 * Um Rundungsfehler zu vermeiden wird der Bruch ueber die Stringdarstellung der Gleitkommazahl ermittelt.
	 * @param gleitKommaZahl Zahl, die in einen Bruch umgewandelt werden soll.
	 */
	public Bruch(double gleitKommaZahl) {

		// Damit keine Rundungsfehler auftreten die Zahl in einen String wandeln
		String ds = "" + gleitKommaZahl;

		// String am Punkt splitten
		// Achtung: Beim Splitten ist der Punkt ein Sonderzeichen,
		// daher der Umweg ueber ein "beliebiges" Zeichen (hier "p")
		ds = ds.replace(".", "p");
		String[] sa = ds.split("p");

		// Zaehler und Nenner bestimmen
		nenner = (int) Math.pow(10, sa[1].length());
		zaehler = (int) (gleitKommaZahl * nenner);

		// Den Bruch kuerzen
		int faktor = ggt(zaehler, nenner);
		nenner /= faktor;
		zaehler /= faktor;
		
		// Die Assertion prueft, ob der Nenner != 0 ist.
		// Falls die Auswertung true ergibt ist alles OK
		assert nenner != 0 : "Division durch 0!";

		// Testen, ob das Ergebnis stimmt oder ob Rundungsfehler vorhanden sind
		assert 1.0 * zaehler / nenner == gleitKommaZahl : "Rundungsfehler!!";
	}

	/**
	 * Angaben ueber ein <tt>Bruch</tt>-Objekt.
	 * 
	 * @return Stringrepraesentation
	 */
	public String toString() {
		return zaehler + " / " + nenner + " = " + (1.0 * zaehler / nenner);
	}

	/**
	 * ggt nach Euklid
	 * 
	 * @param x Zahl1
	 * @param y Zahl2
	 * @return ggt(x,y)
	 */
	private static int ggt(int x, int y) {
		if (y == 0)
			return x;
		else
			return ggt(y, x % y);
	}
}
