#java #biginteger #comparable
#java #biginteger #сопоставимый
Вопрос:
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() amp;amp; k <= n2.intValue(); k ) {
if (n1.intValue() % k == 0 amp;amp; 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. Почему вы не используете метод BigInteger.gcd?
2. Напишите несколько тестов JUnit для всех отдельных методов, чтобы увидеть, какие из них работают, а какие нет.
3. Я новичок в этом. Эта программа была переписана с Rational с использованием long на BigInteger. Проблема, с которой я сталкиваюсь, заключается в том, что знаменатель периодически становится равным нулю.
Ответ №1:
Проблема в этой строке:
this.denominator = this.denominator.abs().divide(gcd);
Измените на:
this.denominator = denominator.abs().divide(gcd);
Первый всегда использует 1 в качестве знаменателя, поскольку именно так он инициализируется.
Однако ваша реализация gcd очень несовершенна…
Комментарии:
1. 1. Это хороший пример ошибок, связанных с использованием одного и того же имени для переменной экземпляра и параметра метода. Вы должны делать это максимум только в простых установщиках.