package sk.upjs.umv;
import java.util.List;
import org.apache.commons.math3.util.ArithmeticUtils;
public class Zlomok extends Number implements Comparable<Zlomok>, Roundable {
private final int citatel;
private final int menovatel;
public static final Zlomok POLOVICA = new Zlomok(1, 2);
public Zlomok(int citatel, int menovatel) {
this.citatel = citatel;
this.menovatel = menovatel;
}
public int getCitatel() {
return citatel;
}
public int getMenovatel() {
return menovatel;
}
@Override
public String toString() {
return citatel + "/" + menovatel;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Zlomok other = (Zlomok) obj;
// dam oba zlomky do zakladneho tvaru a tie porovnam
int thisGcd = ArithmeticUtils.gcd(getCitatel(), getMenovatel());
int otherGcd = ArithmeticUtils.gcd(other.getCitatel(), other.getMenovatel());
return getCitatel() / thisGcd == other.getCitatel() / otherGcd
&& getMenovatel() / thisGcd == other.getMenovatel() / otherGcd;
}
// Euclidov algoritmus
@Override
public int hashCode() {
int thisGcd = ArithmeticUtils.gcd(getCitatel(), getMenovatel());
return getCitatel() / thisGcd + getMenovatel() / thisGcd;
}
public Zlomok pripocitaj(Zlomok z) {
int novyCitatel = this.getCitatel() * z.getMenovatel() + z.getCitatel() * this.getMenovatel();
int novyMenovatel = this.getMenovatel() * z.getMenovatel();
return new Zlomok(novyCitatel, novyMenovatel);
}
public Zlomok normalizuj() {
// int gcd = ArithmeticUtils.gcd(getCitatel(), getMenovatel());
int gcd = najvacsiSpolocnyDelitel(getCitatel(), getMenovatel());
int novyCitatel = 0;
int novyMenovatel = 0;
if (getMenovatel() < 0) {
novyMenovatel = -getMenovatel();
novyCitatel = -getCitatel();
return new Zlomok(novyCitatel / gcd, novyMenovatel / gcd);
}
return new Zlomok(getCitatel() / gcd, getMenovatel() / gcd);
}
private int najvacsiSpolocnyDelitel(int cislo1, int cislo2) {
return ArithmeticUtils.gcd(cislo1, cislo2);
}
public double getDoubleValue() {
return (double) getCitatel() / getMenovatel();
}
@Override
public double doubleValue() {
return getDoubleValue();
}
@Override
public float floatValue() {
return (float) getDoubleValue();
}
@Override
public int intValue() {
return (int) getDoubleValue();
}
@Override
public long longValue() {
return (long) getDoubleValue();
}
@Override
public int compareTo(Zlomok o) {
// porovnavanie na zaklade hodnot
// return Double.compare(getDoubleValue(), o.getDoubleValue());
// 2/6, 1/3, 2/3, 1/2, 20/40
// 1/3, 2/6, 1/2, 20/40, 2/3
// porovnavanie na zaklade hodnot a ak maju zlomky rovnaku hodnotu,
// tak porovnavanie na zaklade menovatelov
int porovnanie = Double.compare(getDoubleValue(), o.getDoubleValue());
if (porovnanie == 0) {
return Integer.compare(getMenovatel(), o.getMenovatel());
}
return porovnanie;
// takto by sme to mohli spravit pre vsetky pripady, ale aktualne to nebudem
// robit
// if (getCitatel() * o.getMenovatel() == getMenovatel() * o.getCitatel()) {
// return 0;
// }
}
public static Zlomok sucet(List<Zlomok> zlomky) {
// int vysledok = 0
// vo for each cykle sme len priratavali hodnoty
// return vysledok;
// Zlomok vysledok = new Zlomok(0, 1);
//
// for (Zlomok zlomok : zlomky) {
// vysledok = vysledok.pripocitaj(zlomok);
// }
//
// return vysledok.normalizuj();
// iny sposob ako implementovat sucet
Zlomok vysledok = null;
for (Zlomok zlomok : zlomky) {
if (vysledok == null) {
vysledok = zlomok;
} else {
vysledok = vysledok.pripocitaj(zlomok);
}
}
return vysledok.normalizuj();
}
@Override
public int roundValue() {
return (int) Math.round(getDoubleValue());
}
public double distanceTo(Zlomok zlomok) {
return Math.abs(getDoubleValue() - zlomok.getDoubleValue());
}
}