25

私の仕事は、合理的なクラスを開発することです。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);
    }  
}
4

6 に答える 6

50

興味深い質問です。最小限のコードでそれを行う実行可能コードを次に示します。

/** @return the greatest common denominator */
public static long gcd(long a, long b) {
    return b == 0 ? a : gcd(b, a % b);
}

public static String asFraction(long a, long b) {
    long gcd = gcd(a, b);
    return (a / gcd) + "/" + (b / gcd);
}

// Some tests
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"
}

ボーナス方法:

/** @return the lowest common multiple */
public static long lcm(long a, long b) {
    return a * b / gcd(a, b);
}

/** @return the greatest common denominator */
public static long gcd(List<? extends Number> numbers) {
    return numbers.stream().map(Number::longValue).reduce((a, b) -> gcd(a, b)).orElseThrow(NoSuchElementException::new);
}

/** @return the lowest common multiple */
public static long lcm(List<? extends Number> numbers) {
    return numbers.stream().map(Number::longValue).reduce((a, b) -> lcm(a, b)).orElseThrow(NoSuchElementException::new);
}
于 2011-07-08T03:12:26.307 に答える
14

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 を見つけたい場合は、おそらく新しい関数を作成する必要があります。少しすっきりして読みやすくなります。その機能もテストできます。

于 2011-07-08T01:41:45.963 に答える
5

参考までに、実装したのは、2 つの数値の最大公約数を計算する元の減法 ユークリッド アルゴリズムです。

はるかに高速なバージョンでは、ループ%の代わりに、整数除算の剰余を使用しています。-

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 を使用します。Matt's answer は、同じアルゴリズムの再帰バージョンを示しています。

于 2011-07-08T02:31:07.947 に答える
1

このクラスは、静的メソッドのコンテナ以外のものにする必要があります。こちらが骸骨

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
    }
}
于 2011-07-09T15:08:05.190 に答える
0

私が使用する同様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())));

    }

}

BigRationalBigInteger分子と分母が含まれています。isInteger()単純化された比率の分母が 1 に等しい場合、true を返します。

于 2016-10-02T03:32:57.150 に答える