Загрузка данных
Мне нужно сделать новую лабораторную работу по старому коду из старой лабораторной работы. Вот условие старой лабораторной работы: Создать класс (классы), указанный в задании. По возможности использовать assert и
исключения для обработки ошибочных ситуаций.
В отдельном файле разработать тестовое приложение, использующее класс (классы),
указанный в задании. Провести тестирование всех методов и конструкторов с выводом данных
и результатов. 8) Рациональная (несократимая) дробь представляется парой целых чисел (a,b),
где a - числитель, b - знаменатель. Создать класс Rational для работы с рациональными
дробями. Необходимо реализовать 4 арифметические операции: +-*/.
Класс должен реализовать:
-интерфейсы Comparable и Comparator с возможностью выбора одного из полей
для сравнения
-интерфейс Iterable - индексатор по всем полям объекта
-метод для сохранения значений всех полей в строке текста (переопределить
toString())
-конструктор или метод для инициализации объекта из строки текста,
соответствующий реализации метода toString()
И вот условие новой лабораторной:
Подробно документируйте своё решение, используя тэги комментариев документации.
Документируйте пакеты, классы и интерфейсы, методы, параметры, исключения,
возвращаемые значения, используемые алгоритмы и т.д. Обязательно укажите автора кода и
версию.
Сгенерируйте результат утилитой javadoc.
На проверку сдаётся результат работы javadoc и исходный код (каталог src проекта,
включая пакеты).
Исходный код старой лабораторной:
Rational.java
package rational_8;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Objects;
public final class Rational implements Comparable<Rational>, Iterable<Integer>, Comparator<Rational> {
public enum Field { NUMERATOR, DENOMINATOR, VALUE, ABS_VALUE }
private final int numerator;
private final int denominator;
private final Field comparatorField;
public Rational(int a, int b) {
if (b == 0) throw new IllegalArgumentException("Знаменатель не может быть равен 0");
if (b < 0) { a = -a; b = -b; }
int g = gcd(Math.abs(a), b);
this.numerator = a / g;
this.denominator = b / g;
this.comparatorField = Field.VALUE;
assert this.denominator > 0 : "После нормализации знаменатель должен быть > 0";
}
public Rational(Rational other) {
this.numerator = other.numerator;
this.denominator = other.denominator;
this.comparatorField = other.comparatorField;
}
public Rational(String s) {
Objects.requireNonNull(s, "Строка не может быть null");
s = s.trim();
int slash = s.indexOf('/');
if (slash < 0) throw new IllegalArgumentException("Неверный формат. Ожидалось a/b");
int a, b;
try {
a = Integer.parseInt(s.substring(0, slash).trim());
b = Integer.parseInt(s.substring(slash + 1).trim());
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("Ошибка при чтении целых чисел: " + s, nfe);
}
if (b == 0) throw new IllegalArgumentException("Знаменатель не может быть равен 0");
if (b < 0) { a = -a; b = -b; }
int g = gcd(Math.abs(a), b);
this.numerator = a / g;
this.denominator = b / g;
this.comparatorField = Field.VALUE;
}
private Rational(int a, int b, Field cmpField) {
this.numerator = a;
this.denominator = b;
this.comparatorField = cmpField;
}
public int getNumerator() { return numerator; }
public int getDenominator() { return denominator; }
public double toDouble() { return (double) numerator / (double) denominator; }
public Rational add(Rational r) {
long n = (long)this.numerator * r.denominator + (long)r.numerator * this.denominator;
long d = (long)this.denominator * r.denominator;
return fromLongs(n, d);
}
public Rational subtract(Rational r) {
long n = (long)this.numerator * r.denominator - (long)r.numerator * this.denominator;
long d = (long)this.denominator * r.denominator;
return fromLongs(n, d);
}
public Rational multiply(Rational r) {
long n = (long)this.numerator * r.numerator;
long d = (long)this.denominator * r.denominator;
return fromLongs(n, d);
}
public Rational divide(Rational r) {
if (r.numerator == 0) throw new ArithmeticException("Деление на ноль");
long n = (long)this.numerator * r.denominator;
long d = (long)this.denominator * r.numerator;
if (d < 0) { n = -n; d = -d; }
return fromLongs(n, d);
}
public int compareTo(Rational o) {
long left = (long)this.numerator * o.denominator;
long right = (long)o.numerator * this.denominator;
return Long.compare(left, right);
}
public static Rational asComparator(Field field) {
return new Rational(0, 1, Objects.requireNonNull(field));
}
public int compare(Rational a, Rational b) {
switch (comparatorField) {
case NUMERATOR: return Integer.compare(a.numerator, b.numerator);
case DENOMINATOR: return Integer.compare(a.denominator, b.denominator);
case ABS_VALUE: return Double.compare(Math.abs(a.toDouble()), Math.abs(b.toDouble()));
case VALUE:
default: return a.compareTo(b);
}
}
public static final Comparator<Rational> BY_NUMERATOR = asComparator(Field.NUMERATOR);
public static final Comparator<Rational> BY_DENOMINATOR = asComparator(Field.DENOMINATOR);
public static final Comparator<Rational> BY_VALUE = asComparator(Field.VALUE);
public static final Comparator<Rational> BY_ABS_VALUE = asComparator(Field.ABS_VALUE);
public Iterator<Integer> iterator() {
return Arrays.asList(numerator, denominator).iterator();
}
public int getField(int index) {
if (index == 0) return numerator;
if (index == 1) return denominator;
throw new IndexOutOfBoundsException("Индекс может быть только 0 (числитель) или 1 (знаменатель)");
}
public String toString() {
return numerator + "/" + denominator;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Rational)) return false;
Rational r = (Rational)o;
return numerator == r.numerator && denominator == r.denominator;
}
public int hashCode() {
return Objects.hash(numerator, denominator);
}
private static Rational fromLongs(long n, long d) {
if (d == 0L) throw new IllegalArgumentException("Знаменатель не может быть равен 0");
if (d < 0) { n = -n; d = -d; }
long g = lgcd(Math.abs(n), d);
n /= g; d /= g;
if (n < Integer.MIN_VALUE || n > Integer.MAX_VALUE || d > Integer.MAX_VALUE)
throw new ArithmeticException("Переполнение при приведении к int");
return new Rational((int)n, (int)d);
}
private static int gcd(int a, int b) {
while (b != 0) {
int t = a % b;
a = b;
b = t;
}
return a == 0 ? 1 : a;
}
private static long lgcd(long a, long b) {
while (b != 0) {
long t = a % b;
a = b;
b = t;
}
return a == 0 ? 1 : a;
}
}
App.java
package rational_8;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class App {
public static void main(String[] args) {
System.out.println("=== Тесты Rational ===");
Rational r1 = new Rational(2, 4);
Rational r2 = new Rational(-3, -9);
Rational r3 = new Rational("-10/20");
Rational r4 = new Rational(5, -15);
Rational r5 = new Rational(r1);
System.out.println("Конструкторы и toString:");
System.out.println("r1 = " + r1 + " (ожид. 1/2)");
System.out.println("r2 = " + r2 + " (ожид. 1/3)");
System.out.println("r3 = " + r3 + " (ожид. -1/2)");
System.out.println("r4 = " + r4 + " (ожид. -1/3)");
System.out.println("r5 = " + r5 + " (копия r1)");
System.out.println("\nАрифметические операции:");
System.out.println(r1 + " + " + r2 + " = " + r1.add(r2));
System.out.println(r1 + " - " + r3 + " = " + r1.subtract(r3));
System.out.println(r2 + " * " + r4 + " = " + r2.multiply(r4));
System.out.println(r1 + " / " + r2 + " = " + r1.divide(r2));
System.out.println("\nСравнение по значению (Comparable):");
System.out.println(r1 + " compareTo " + r2 + " = " + r1.compareTo(r2));
System.out.println(r4 + " compareTo " + r3 + " = " + r4.compareTo(r3));
List<Rational> list = new ArrayList<>(Arrays.asList(
r1, r2, r3, r4, new Rational(7, 8), new Rational(9, 10), new Rational(-2, 7)
));
System.out.println("\nИсходный список:");
System.out.println(list);
list.sort(Rational.BY_VALUE);
System.out.println("\nСортировка по значению:");
System.out.println(list);
list.sort(Rational.BY_NUMERATOR);
System.out.println("\nСортировка по числителю:");
System.out.println(list);
list.sort(Rational.BY_DENOMINATOR);
System.out.println("\nСортировка по знаменателю:");
System.out.println(list);
list.sort(Rational.BY_ABS_VALUE);
System.out.println("\nСортировка по |значению|:");
System.out.println(list);
System.out.println("\nИтерация по полям r1:");
for (int field : r1) {
System.out.println(field);
}
System.out.println("indexer getField(0)=" + r1.getField(0) + ", getField(1)=" + r1.getField(1));
System.out.println("\nequals/hashCode:");
Rational r6 = new Rational(50, 100);
System.out.println(r1 + " equals " + r6 + " → " + r1.equals(r6));
System.out.println("hashCodes: " + r1.hashCode() + " vs " + r6.hashCode());
System.out.println("toDouble(" + r1 + ") = " + r1.toDouble());
System.out.println("\nНегативные тесты:");
try {
new Rational(1, 0);
} catch (Exception e) {
System.out.println("Ожидаемая ошибка: " + e.getMessage());
}
try {
new Rational("3/0");
} catch (Exception e) {
System.out.println("Ожидаемая ошибка: " + e.getMessage());
}
try {
System.out.println(r1 + " / 0 = " + r1.divide(new Rational(0, 5)));
} catch (Exception e) {
System.out.println("Ожидаемая ошибка: " + e.getMessage());
}
System.out.println("\n=== Готово ===");
}
}