Загрузка данных


Мне нужно сделать новую лабораторную работу по старому коду из старой лабораторной работы. Вот условие старой лабораторной работы: Создать класс (классы), указанный в задании. По возможности использовать 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=== Готово ===");
    }
}