package mathe; /** * Bearbeitung von Brüchen. * * @author Daniel Weschke * */ public class Bruch{ int zähler; int nenner; /** * Bruch mit Nenner 1. */ public Bruch(){ nenner = 1; } /** * Bruch mitübergebenen zähler und Nenner 1. * * @param z zähler */ public Bruch(int z){ this(); zähler = z; } /** * Bruch mitübergebenen zähler und Nenner. * * @param z zähler * @param n Nenner */ public Bruch(int z, int n){ this(z); if(n>0) nenner = n; } /** * 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()); zähler = (int) (gleitKommaZahl * nenner); // Den Bruch kuerzen int faktor = ggt_fast(zähler, nenner); nenner /= faktor; zähler /= 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 * zähler / nenner == gleitKommaZahl : "Rundungsfehler!!"; } /** * Addition zweier Brüche. * * @param a zu addierender Bruch * @return Summe */ public Bruch plus(Bruch a){ return new Bruch(zähler*a.nenner+a.zähler*nenner,nenner*a.nenner); } /** * Subtraktion zweier Brüche. * * @param a zu subtrahierender Bruch * @return Differenz */ public Bruch minus(Bruch a){ Bruch b = new Bruch(-a.zähler,a.nenner); return this.plus(b); } /** * Multikation zweier Brüche. * * @param a zu multiplizierder Bruch * @return Produkt */ public Bruch mal(Bruch a){ return new Bruch(zähler*a.zähler,nenner*a.nenner); } /** * Division zweier Brüche. * * @param a zu dividierender Bruch * @return Verhältnis */ public Bruch durch(Bruch a){ return this.mal(a.kehrwert()); } /** * Kehrwert vom Bruch. * * @return Reziprok */ public Bruch kehrwert(){ return new Bruch(nenner,zähler); } /** * Gößten gemeinsamen Teiler vom Bruch. * Nach dem klassischen euklidischen Algorithmus. * * @return größten gemeinsamen Teiler */ public int ggt(){ int a = zähler<0 ? -zähler : zähler; int b = nenner<0 ? -nenner : nenner; if(a>0 && b>0){ while(a!=b){ if(a>b){ a = a - b; } else { b = b - a; } } } return a; } /** * Größter gemeinsamer Teiler vom Bruch. * Nach dem modernen euklidischen Algorithmus. * * @return größten gemeinsamen Teiler */ public int ggt_fast(){ int a = zähler<0 ? -zähler : zähler; int b = nenner<0 ? -nenner : nenner; int c; if(a>0 && b>0){ while(b!=0){ c = a%b; a = b; b = c; } } return a; } /** * Größter gemeinsamer Teiler vom Bruch. * Nach dem modernen euklidischen Algorithmus. * * @return größten gemeinsamen Teiler */ public int ggt_fast(int zähler, int nenner){ int a = zähler<0 ? -zähler : zähler; int b = nenner<0 ? -nenner : nenner; int c; if(a>0 && b>0){ while(b!=0){ c = a%b; a = b; b = c; } } return a; } /** * Kürzen des Bruches. * * @return gekürzter Bruch */ public Bruch kürzen(){ if(zähler!=0 && nenner!=0) return new Bruch(zähler/ggt(),nenner/ggt()); else return this; } /** * Vergleich zweier Brüche. * * @param q zu vergleichender Bruch * @return Bitcode:
* 1 Bruch ist größer
* -1 Bruch ist kleiner
* 0 Bruch ist gleich groß
*/ public int compareTo(Bruch q){ double a = (double) zähler/nenner; double b = (double) q.zähler/q.nenner; if(a > b) return 1; else if(a < b) return -1; else return 0; } /** * Textumwandlung zur Ausgabe. */ @Override public String toString(){ Bruch a = this.kürzen(); if(a.nenner!=1) return new String(a.zähler + "/" + a.nenner); else return new String(""+a.zähler); } }