Использование BigInteger для расчета серии - PullRequest
1 голос
/ 09 ноября 2011
import java.math.BigInteger;

public class Rational extends Number implements Comparable {
  // Data fields for numerator and denominator
  private BigInteger numerator = new BigInteger("0");
  private BigInteger denominator = new BigInteger("1");

  /** Construct a rational with default properties */
  public Rational() {
    this(BigInteger.valueOf(0), BigInteger.valueOf(1));
  }

  /** Construct a rational with specified numerator and denominator */ 
  public Rational(BigInteger numerator, BigInteger denominator) {
    BigInteger gcd = gcd(numerator, denominator);
    this.numerator = BigInteger.valueOf(denominator.signum()).multiply(numerator).divide(gcd);
    this.denominator = this.denominator.abs().divide(gcd); 
  }

  /** Find GCD of two numbers */ 
  private static BigInteger gcd(BigInteger n, BigInteger d) {
    BigInteger n1 = n.abs();
    BigInteger n2 = d.abs();
    BigInteger gcd = new BigInteger("1");

    for (int k = 1; k <= n1.intValue() && k <= n2.intValue(); k++) {
      if (n1.intValue() % k == 0 && n2.intValue() % k == 0)
        gcd = BigInteger.valueOf(k);
    }

    return gcd;
  }

  /** Return numerator */
  public BigInteger getNumerator() {
    return numerator;
  }

  /** Return denominator */
  public BigInteger getDenominator() {
    return denominator;
  }

  /** Add a rational number to this rational */
  public Rational add(Rational secondRational) {
    BigInteger n = (numerator.multiply(secondRational.getDenominator())).add(denominator.multiply(secondRational.getNumerator()));
    BigInteger d = denominator.multiply(secondRational.getDenominator());
    return new Rational(n, d); 
  }

  /** Subtract a rational number from this rational */
  public Rational subtract(Rational secondRational) {
    BigInteger n = (numerator.multiply(secondRational.getDenominator())).subtract(denominator.multiply(secondRational.getNumerator()));
    BigInteger d = denominator.multiply(secondRational.getDenominator());
    return new Rational(n, d);
  }

  /** Multiply a rational number to this rational */
  public Rational multiply(Rational secondRational) {
    BigInteger n = numerator.multiply(secondRational.getNumerator());
    BigInteger d = denominator.multiply(secondRational.getDenominator());
    return new Rational(n, d);
  }

  /** Divide a rational number from this rational */
  public Rational divide(Rational secondRational) {
    BigInteger n = numerator.multiply(secondRational.getDenominator());
    BigInteger d = denominator.multiply(secondRational.numerator);
    return new Rational(n, d);
  }

  /** Override the toString() method */
  public String toString() {
    if (denominator.intValue() == 1)
      return numerator + "";
    else
      return numerator + "/" + denominator;
  }

  /** Override the equals method in the Object class */


  public boolean equals(Object parm1) {
    if ((this.subtract((Rational)(parm1)).getNumerator()).intValue() == 0) 
        return true;
    else
      return false;
  }

  /** Override the abstract intValue method in java.lang.Number */
  public int intValue() {
    return (int)doubleValue();
  }

  /** Override the abstract floatValue method in java.lang.Number */
  public float floatValue() {
    return (float)doubleValue();
  }

  /** Override the doubleValue method in java.lang.Number */
  public double doubleValue() {
    return numerator.divide(denominator).doubleValue();
  }

  /** Override the abstract BigIntegerValue method in java.lang.Number */
  public long longValue() {
    return (long)doubleValue();
  }

  /** Override the compareTo method in java.lang.Comparable */
  public int compareTo(Object o) {
    if (((this.subtract((Rational)o)).getNumerator()).intValue() > 0)
      return 1;
    else if (((this.subtract((Rational)o)).getNumerator()).intValue() < 0)
      return -1;
    else
      return 0;
  }

  public static void main(String[] args) {
    // Create and initialize two rational numbers r1 and r2.
    Rational r1 = new Rational(BigInteger.valueOf(1), BigInteger.valueOf(2));
    Rational r2 = new Rational(BigInteger.valueOf(1), BigInteger.valueOf(2));

    for (int i = 2; i <= 100; i++){
        r2.numerator = BigInteger.valueOf(i);
        r2.denominator = r2.denominator.add(BigInteger.valueOf(1));


        System.out.println("r2: " + r2.getNumerator() + "/" + r2.getDenominator());

        r1 = r1.add(r2);        
    }
    // Display results 

    System.out.println("r1: " + r1.getNumerator() + "/" + r1.getDenominator());
  }

Я работал над этим в течение нескольких часов, и я врезался в стену. Цель состоит в том, чтобы использовать BigInteger для суммирования ряда дробей. По некоторым причинам числитель и знаменатель r2 равны, когда они должны быть 1/2. Конечный результат также неверен, так как знаменатель не должен быть равен 0. Что мне не хватает или что я делаю неправильно?

1 Ответ

1 голос
/ 09 ноября 2011

Проблема в этой строке:

this.denominator = this.denominator.abs().divide(gcd); 

Изменить на:

this.denominator = denominator.abs().divide(gcd); 

Первый всегда использует 1 в качестве знаменателя, так как он инициализируется.

Однако ваша реализация gcd ОЧЕНЬ неэффективна ...

...