Упрощение дробей в Java
Моя задача - разработать рациональный класс. Если 500 и 1000 - мои входы, тогда (½) должен быть моим выходом.
Я написал программу самостоятельно, чтобы найти ее.
Есть ли другой лучший способ найти решение, или моя программа уже самая лучшая?
public class Rational {
public static void main(String[] args){
int n1 = Integer.parseInt(args[0]);
int n2 = Integer.parseInt(args[1]);
int temp1 = n1;
int temp2 = n2;
while (n1 != n2){
if(n1 > n2)
n1 = n1 - n2;
else
n2 = n2 - n1;
}
int n3 = temp1 / n1 ;
int n4 = temp2 / n1 ;
System.out.print("\n Output :\n");
System.out.print(n3 + "/" + n4 + "\n\n" );
System.exit(0);
}
}
Ответы
Ответ 1
Интересный вопрос. Вот несколько исполняемых кода, которые делают это всего за пару строк:
/** @return the greatest common denominator */
public static long gcm(long a, long b) {
return b == 0 ? a : gcm(b, a % b); // Not bad for one line of code :)
}
public static String asFraction(long a, long b) {
long gcm = gcm(a, b);
return (a / gcm) + "/" + (b / gcm);
}
public static void main(String[] args) {
System.out.println(asFraction(500, 1000)); // "1/2"
System.out.println(asFraction(17, 3)); // "17/3"
System.out.println(asFraction(462, 1071)); // "22/51"
}
Ответ 2
Вам нужен GCD. Либо используйте BigInteger, как упоминал Натан, или если вы не можете, используйте свой собственный.
public int GCD(int a, int b){
if (b==0) return a;
return GCD(b,a%b);
}
Затем вы можете разделить каждое число на GCD, как вы это делали выше.
Это даст вам неправильную долю. Если вам нужна смешанная фракция, вы можете получить новые цифры. Пример, если у вас было 1500 и 500 для ввода, в итоге вы получите 3/2. Может быть, вы хотите 1 1/2. Таким образом, вы просто разделите 3/2 и получите 1, а затем получите оставшуюся часть 3/2, которая также равна 1. Знаменатель останется прежним.
whole = x/y;
numerator x%y;
denominator = y;
Если вы не верите мне, что это работает, вы можете проверить
http://en.wikipedia.org/wiki/Euclidean_algorithm
Мне просто нравится рекурсивная функция, потому что она чистая и простая.
Ваш алгоритм близок, но не совсем корректен. Кроме того, вы должны создать новую функцию, если хотите найти gcd. Просто делает его немного чище и легче читать. Вы также можете проверить эту функцию.
Ответ 3
Для справки, вы реализовали оригинальный субтрактивный Евклидовой алгоритм для вычисления наибольший общий делитель из двух чисел.
Более быстрая версия использует остаток от целочисленного деления, например. %
вместо -
в вашем цикле:
while (n1 != 0 && n2 != 0){
if(n1 > n2)
n1 = n1 % n2;
else
n2 = n2 % n1;
}
... и затем убедитесь, что вы будете использовать тот, который не равен нулю.
Более оптимизированная версия будет следующей:
while(n1 != 0) {
int old_n1 = n1;
n1 = n2 % n1;
n2 = old_n1;
}
а затем используйте n1. Мэтт ответ показывает рекурсивную версию того же алгоритма.
Ответ 4
Вы должны сделать этот класс чем-то иным, чем контейнером для статических методов. Вот скелет
import java.math.BigInteger;
public class BigRational
{
private BigInteger num;
private BigInteger denom;
public BigRational(BigInteger _num, BigInteger _denom)
{
//put the negative on top
// reduce BigRational using the BigInteger gcd method
}
public BigRational()
{
this(BigInteger.ZERO, BigInteger.ONE);
}
public BigRational add(BigRational that)
{
// return this + that;
}
.
.
.
//etc
}
}
Ответ 5
У меня есть аналогичный класс BigRational
, который я использую. GcdFunction
использует функцию BigInteger
gcd
:
public class GcdFunction implements BinaryFunction {
@Override
public BigRational apply(final BigRational left, final BigRational right) {
if (!(left.isInteger() && right.isInteger())) {
throw new EvaluationException("GCD can only be applied to integers");
}
return new BigRational(left.getNumerator().gcd((right.getNumerator())));
}
}
BigRational
содержит числитель и знаменатель BigInteger
. isInteger()
возвращает значение true, если упрощенное значение знаменателя равно 1.