simplifying fractions in Java

会有一股神秘感。 提交于 2019-11-29 05:32:09

Interesting question. Here's some executable code that does it in just a couple of lines:

/** @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"
}

You need the GCD. Either use BigInteger like Nathan mentioned or if you can't, use your own.

public int GCD(int a, int b){
   if (b==0) return a;
   return GCD(b,a%b);
}

Then you can divide each number by the GCD, like you have done above.

This will give you an improper fraction. If you need a mixed fraction then you can get the new numbers. Example if you had 1500 and 500 for inputs you would end up with 3/2 as your answer. Maybe you want 1 1/2. So you just divide 3/2 and get 1 and then get the remainder of 3/2 which is also 1. The denominator will stay the same.

whole = x/y;
numerator x%y;
denominator = y;

In case you don't believe me that this works, you can check out http://en.wikipedia.org/wiki/Euclidean_algorithm

I just happen to like the recursive function because it's clean and simple.

Your algorithm is close, but not exactly correct. Also, you should probably create a new function if you want to find the gcd. Just makes it a little cleaner and easier to read. You can also test that function as well.

Paŭlo Ebermann

For reference, what you implemented is the original subtractive Euclidean Algorithm to calculate the greatest common divisor of two numbers.

A lot faster version is using the remainder from integer division, e.g. % instead of - in your loop:

while (n1 != 0 && n2 != 0){
  if(n1 > n2)
     n1 = n1 % n2;
  else
     n2 = n2 % n1;
}

... and then make sure you will use the one which is not zero.

A more streamlined version would be this:

while(n1 != 0) {
   int old_n1 = n1;
   n1 = n2 % n1;
   n2 = old_n1;
}

and then use n1. Matt's answer shows a recursive version of the same algorithm.

You should make this class something other than a container for static methods. Here is a skeleton

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
    }
}

I have a similar BigRational class I use. The GcdFunction is makes use of BigInteger's gcd function:

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 contains a BigInteger numerator and denominator. isInteger() returns true if the simplified ratio's denominator is equal to 1.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!