Brüche in Java

Rashmi Patidar 12 Oktober 2023
Brüche in Java

Mathematisch sind Brüche die Teile oder Abschnitte von Werten. Wenn ein Objekt in bestimmten Proportionen gleichmäßig gebrochen wird, wird der gebildete Wert Bruch genannt. Brüche werden in rationale und irrationale Zahlen eingeteilt.

In der Programmiersprache Java gibt es das Privileg, verschiedene Operationen über Brüche wie mathematische Prozeduren auszuführen. Man kann die Bruchzahlen addieren, subtrahieren, multiplizieren und dividieren.

Unten ist der Codeblock, der die rationalen Zahlenoperationen in der benutzerdefinierten Klasse demonstriert.

import java.math.BigInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RationalNumber {
  public final static RationalNumber ZERO = new RationalNumber(BigInteger.ZERO, BigInteger.ONE);

  private final BigInteger numerator, denominator;

  private RationalNumber(BigInteger numerator, BigInteger denominator) {
    this.numerator = numerator;
    this.denominator = denominator;
  }

  private static RationalNumber canonical(
      BigInteger numerator, BigInteger denominator, boolean checkGcd) {
    if (denominator.signum() == 0) {
      throw new IllegalArgumentException("denominator is zero");
    }
    if (numerator.signum() == 0) {
      return ZERO;
    }
    if (denominator.signum() < 0) {
      numerator = numerator.negate();
      denominator = denominator.negate();
    }
    if (checkGcd) {
      BigInteger gcd = numerator.gcd(denominator);
      if (!gcd.equals(BigInteger.ONE)) {
        numerator = numerator.divide(gcd);
        denominator = denominator.divide(gcd);
      }
    }
    return new RationalNumber(numerator, denominator);
  }

  public static RationalNumber getInstance(long numerator, long denominator) {
    return canonical(new BigInteger("" + numerator), new BigInteger("" + denominator), true);
  }

  public static RationalNumber valueOf(String s) {
    Pattern p = Pattern.compile("(-?\\d+)(?:.(\\d+)?)?0*(?:e(-?\\d+))?");
    Matcher m = p.matcher(s);
    if (!m.matches()) {
      throw new IllegalArgumentException("Unknown format '" + s + "'");
    }
    String whole = m.group(1);
    String decimal = m.group(2);
    String exponent = m.group(3);
    String n = whole;
    if (decimal != null) {
      n += decimal;
    }
    BigInteger numerator = new BigInteger(n);
    int exp = exponent == null ? 0 : Integer.valueOf(exponent);
    int decimalPlaces = decimal == null ? 0 : decimal.length();
    exp -= decimalPlaces;
    BigInteger denominator;
    if (exp < 0) {
      denominator = BigInteger.TEN.pow(-exp);
    } else {
      numerator = numerator.multiply(BigInteger.TEN.pow(exp));
      denominator = BigInteger.ONE;
    }

    return canonical(numerator, denominator, true);
  }

  public static void main(String[] args) {
    RationalNumber r1 = RationalNumber.valueOf("3.14e4");
    RationalNumber r2 = RationalNumber.getInstance(111, 7);
    convert("r1", r1);
    convert("r2", r2);
    convert("r1 + r2", r1.add(r2));
    convert("r1 - r2", r1.subtract(r2));
    convert("r1 * r2", r1.multiply(r2));
    convert("r1 / r2", r1.divide(r2));
    convert("r2 ^ 2", r2.pow(2));
  }

  public static void convert(String name, RationalNumber r) {
    System.out.printf("%s = %s%n", name, r);
    System.out.printf("%s.negate() = %s%n", name, r.negate());
    System.out.printf("%s.invert() = %s%n", name, r.invert());
    System.out.printf("%s.intValue() = %,d%n", name, r.intValue());
    System.out.printf("%s.longValue() = %,d%n", name, r.longValue());
    System.out.printf("%s.floatValue() = %,f%n", name, r.floatValue());
    System.out.printf("%s.doubleValue() = %,f%n", name, r.doubleValue());
    System.out.println();
  }

  public RationalNumber add(RationalNumber o) {
    if (o.numerator.signum() == 0) {
      return this;
    } else if (numerator.signum() == 0) {
      return o;
    } else if (denominator.equals(o.denominator)) {
      return new RationalNumber(numerator.add(o.numerator), denominator);
    } else {
      return canonical(numerator.multiply(o.denominator).add(o.numerator.multiply(denominator)),
          denominator.multiply(o.denominator), true);
    }
  }

  public RationalNumber multiply(RationalNumber o) {
    if (numerator.signum() == 0 || o.numerator.signum() == 0) {
      return ZERO;
    } else if (numerator.equals(o.denominator)) {
      return canonical(o.numerator, denominator, true);
    } else if (o.numerator.equals(denominator)) {
      return canonical(numerator, o.denominator, true);
    } else if (numerator.negate().equals(o.denominator)) {
      return canonical(o.numerator.negate(), denominator, true);
    } else if (o.numerator.negate().equals(denominator)) {
      return canonical(numerator.negate(), o.denominator, true);
    } else {
      return canonical(numerator.multiply(o.numerator), denominator.multiply(o.denominator), true);
    }
  }

  public boolean isInteger() {
    return numerator.signum() == 0 || denominator.equals(BigInteger.ONE);
  }

  public RationalNumber negate() {
    return new RationalNumber(numerator.negate(), denominator);
  }

  public RationalNumber invert() {
    return canonical(denominator, numerator, false);
  }

  public RationalNumber pow(int exp) {
    return canonical(numerator.pow(exp), denominator.pow(exp), true);
  }

  public RationalNumber subtract(RationalNumber o) {
    return add(o.negate());
  }

  public RationalNumber divide(RationalNumber o) {
    return multiply(o.invert());
  }

  public int intValue() {
    return isInteger() ? numerator.intValue() : numerator.divide(denominator).intValue();
  }

  public long longValue() {
    return isInteger() ? numerator.longValue() : numerator.divide(denominator).longValue();
  }

  public float floatValue() {
    return (float) doubleValue();
  }

  public double doubleValue() {
    return isInteger() ? numerator.doubleValue()
                       : numerator.doubleValue() / denominator.doubleValue();
  }

  @Override
  public String toString() {
    return isInteger() ? String.format("%,d", numerator)
                       : String.format("%,d / %,d", numerator, denominator);
  }
}

Im obigen Programm beginnt die Ausführung mit der Methode main. Zunächst wird eine rationale Zahl mit der in der Klasse definierten statischen Funktion valueOf() initialisiert. Es nimmt einen Zeichenkettenwert an und führt Manipulationen an der EingabeZeichenkette durch.

Es gibt eine RationalNumber des benutzerdefinierten Typs zurück. Die Funktion sucht zuerst nach einem Eingabe-String mit den richtigen Validierungen und Mustern. Der Eingabe-String wird in Exponenten, Dezimalzahlen und den ganzen Teil getrennt. Diese einzelnen gebrochenen Werte verbinden sich zu einer rationalen Zahl.

Eine andere Möglichkeit, eine rationale Zahl zu erzeugen, ist die Verwendung einer statischen Factory-Funktion instanceOf(). Die Methode ruft intern die Funktion canonical auf, die einen privaten Konstruktor der Klasse aufruft. Der Konstruktor trennt und legt die Werte von Zähler und Nenner für eine bestimmte Instanz fest. Mit kanonischer Form ist einfach die Standarddarstellungsform der rationalen Zahl gemeint.

Im gegebenen Fall ist p/q die Standard- oder kanonische Form, wobei q!=0 immer wahr sein sollte. Die Methode hat die Logik geschrieben, um die Grundbedingungen einer rationalen Zahl zu erfüllen. Es prüft das Vorzeichen von Zähler und Nenner getrennt und führt Operationen durch. Es prüft auf Nennerwerte; wenn es null ist, wirft die Operation eine Exception. Es prüft auch auf den größten gemeinsamen Teiler oder gcd in den Zähler- und Nennerwerten. Die Funktion gcd ist in der Klasse BigInteger vorhanden, die einen BigInteger-Wert zurückgibt.

Im weiteren Verlauf wird die Methode convert aufgerufen, die die erste erzeugte Instanz der rationalen Zahl übergibt. Auch diese Methode ruft über die übergebene Instanz rationale Zahl sieben verschiedene Funktionen auf.

Im Folgenden werden Sie jede dieser Methoden besser verstehen:

  • Drucken Sie die rationale Zahl im Druckstrom. Im Allgemeinen wird bei jeder Ausgabe einer Instanz die Standardmethode toString aufgerufen. Die Methode gibt den Namen der Klasse gefolgt von der hexadezimalen Darstellung des Speicherorts aus. Aber hier wird die Funktion überschrieben, um eine andere Implementierung zu erhalten, die die Zahl in der Form p/q darstellt.
  • Die Funktion negate negiert intern die rationale Zahl, indem sie die Methode negate der Klasse BigInteger aufruft. Es wird ein Minuszeichen vor der rationalen Zahl hinzugefügt.
  • Die Invert-Funktion ruft intern die canonical Methode mit einem einzigen Unterschied auf. Es übergibt intern den dritten checkGcd-Parameter als false. Wenn der Eingabewert Boolean true ist, vereinfacht die Methodenlogik die rationale Zahl, indem sie den Bruch durch seinen größten gemeinsamen Teiler dividiert. Aber in diesem Fall besteht die Notwendigkeit, ohne Vereinfachung zu invertieren.
  • Die Funktion intValue prüft zunächst, ob die Instanz ein Integer-Wert ist. Integers sind Zahlen, die positiv, negativ oder null sein können, aber keine Brüche sein können. Intern ruft es also die Methode divide über Zähler und Nenner auf. Die Methode wird in der Klasse BigInteger angegeben und gibt einen BigInteger-Wert zurück. Es wirft auch ArithmeticException, wenn der Nenner einen Null-Wert findet. Der zurückgegebene Wert wird mit der Funktion intValue in einen int-Wert umgewandelt.
  • Die Funktion longValue ruft intern die Divide-Funktion auf und analysiert die Ausgabe von BigInteger auf den Datentyp long.
  • Die Funktion floatValue liefert den Gleitkommawert der rationalen Zahl. Und so wie die Funktion doubleValue(), die die Ausgabe in den Datentyp Double umwandelt.

Der gesamte Prozess wird von einer anfänglichen rationalen Zahlinstanz aufgerufen, die die r1-Instanz ist. Eine ähnliche Sequenz wird noch einmal wiederholt und für die rationale Instanz r2 ausgegeben.

Mathematische Operationen für Brüche in Java

Addieren, subtrahieren, dividieren, multiplizieren und arithmetische Operationen benötigen nun zwei Operanden zur Auswertung. Lassen Sie uns die Methoden im Folgenden im Detail besprechen:

  1. Die Funktion add prüft zuerst, ob die Zählerwerte positiv, negativ oder null sind. Falls nicht Null, prüft es, ob die Nenner der beiden rationalen Zahlen gleich sind. Wenn das gleiche gefunden wird, addiert es den Zählerwert und gibt die gebildete rationale Zahl zurück. Andernfalls, wenn es nicht ähnlich gefunden wird, definiert es die Logik für die Addition rationaler Zahlen.
  2. Die Methode subtract ruft intern die Methode add auf, nachdem die zweite übergebene Instanz der rationalen Zahl negiert wurde.
  3. Die Methode multiply hat intern eine recht komplexe Logik. Es prüft, ob der Zähler Null einer der rationalen Zahlen ist, und gibt die Ausgabe als Nullwert zurück. Falls nicht Null, überprüft es den Zähler mit dem Nenner einer der beiden Mengen. Das heißt, der Zähler r1 wird mit dem Nenner r2 überprüft und umgekehrt. Wenn keine Bedingung zutrifft, wird der Zähler von r1 mit dem Instanzzähler r2 multipliziert, und die Nenner von beiden werden multipliziert. Schließlich ruft es die Funktion multiply der Klasse BigInteger auf, um die Multiplikation durchzuführen.
  4. Die Funktion divide invertiert die übergebene Instanz und ruft intern die Funktion multiply mit der ersten Instanz auf.
  5. Zuletzt ist die Funktion pow, die die zweite Potenz der Instanz r2 auswertet. Die Implementierung von pow wird in der Klasse BigInteger definiert, die den Exponenten zur Auswertung verwendet. Die Methode löst die Ausnahme ArithmeticException aus, wenn der Exponent einen negativen Wert hat.

Unten ist die Ausgabe des oben angegebenen komplexen Codes:

r1 = 31, 400 r1.negate() = -31, 400 r1.invert() = 1 / 31, 400 r1.intValue() = 31,
             400 r1.longValue() = 31, 400 r1.floatValue() = 31, 400.000000 r1.doubleValue() = 31,
             400.000000

    r2 = 111 / 7 r2.negate() = -111 / 7 r2.invert() = 7 / 111 r2.intValue() = 15 r2.longValue() =
        15 r2.floatValue() = 15.857142 r2.doubleValue() = 15.857143

    r1
    + r2 = 219,
             911 / 7 r1 + r2.negate() = -219, 911 / 7 r1 + r2.invert() = 7 / 219,
             911 r1 + r2.intValue() = 31, 415 r1 + r2.longValue() = 31,
             415 r1 + r2.floatValue() = 31, 415.857422 r1 + r2.doubleValue() = 31,
             415.857143

    r1
    - r2 = 219,
             689 / 7 r1 - r2.negate() = -219, 689 / 7 r1 - r2.invert() = 7 / 219,
             689 r1 - r2.intValue() = 31, 384 r1 - r2.longValue() = 31,
             384 r1 - r2.floatValue() = 31, 384.142578 r1 - r2.doubleValue() = 31,
             384.142857

    r1* r2 = 3,
             485, 400 / 7 r1* r2.negate() = -3, 485, 400 / 7 r1* r2.invert() = 7 / 3, 485,
             400 r1* r2.intValue() = 497, 914 r1* r2.longValue() = 497,
             914 r1* r2.floatValue() = 497, 914.281250 r1* r2.doubleValue() = 497,
             914.285714

    r1
    / r2 = 219,
             800 / 111 r1 / r2.negate() = -219, 800 / 111 r1 / r2.invert() = 111 / 219,
             800 r1 / r2.intValue() = 1, 980 r1 / r2.longValue() = 1, 980 r1 / r2.floatValue() = 1,
             980.180176 r1 / r2.doubleValue() = 1,
             980.180180

    r2
    ^ 2 = 12,
             321 / 49 r2 ^ 2.negate() = -12, 321 / 49 r2 ^ 2.invert() = 49 / 12,
             321 r2 ^ 2.intValue() = 251 r2 ^ 2.longValue() = 251 r2
    ^ 2.floatValue() = 251.448975 r2 ^ 2.doubleValue() = 251.448980
Rashmi Patidar avatar Rashmi Patidar avatar

Rashmi is a professional Software Developer with hands on over varied tech stack. She has been working on Java, Springboot, Microservices, Typescript, MySQL, Graphql and more. She loves to spread knowledge via her writings. She is keen taking up new things and adopt in her career.

LinkedIn

Verwandter Artikel - Java Math