CodeGym /Java Blog /ランダム /階乗用の Java プログラム
John Squirrels
レベル 41
San Francisco

階乗用の Java プログラム

ランダム グループに公開済み
今日は階乗と階乗を求める最も一般的な方法について説明します。これは、プログラマが知っていて操作できるようにする必要がある最も基本的な関数の 1 つです。さて、始めましょう。数値 n の階乗 (n! と表記) は、1 から n までのすべての自然数の積 (乗算) の値です。これは次のようになります (数学の知識を復習しましょう)。
1! = 1 2! = 1 * 2 = 2 3! = 1 * 2 * 3 = 6 4! = 1 * 2 * 3 * 4 = 24 5! = 1 * 2 * 3 * 4 * 5 = 120
そして、0 にはもう 1 つの小さなルールがあります。
!0 = 1
6の差を計算したい場合! そして4!:
6!-4! = 1⋅2⋅3⋅4⋅5⋅6 - 1⋅2⋅3⋅4 = 720 - 24 = 696
これをプログラミングで実装するとどうなるかを見てみましょう。Java で階乗の計算を行う方法をいくつか見ていきます。

階乗計画法における通常の解法

ループを使用した簡単な階乗プログラムを次に示します。

class FactorialExample{  
 public static void main(String args[]){  
  int i,fact=1;  
  int number=7;// our number to do the necessary calculations in class Factorial    
  for(i=1;i<=number;i++){    
      fact=fact*i;    
  }    
  System.out.println("Factorial of "+number+" is: "+fact);    
 }  
}
コンソール上の出力は次のようになります。
7 の階乗は: 5040
物事を整理するためのもう 1 つの例:

public static int getFactorial(int f) {
  int result = 1;
  for (int i = 1; i <= f; i++) {
     result = result * i; // finding factorial of number using loops
  }
  return result;
}
ここでは何も難しいことはありません。渡された数値をループのサイズとして使用し、f に到達するまで前の数値をすべて乗算します。そしてメインでは:

System.out.println(getFactorial(6) - getFactorial(4));
コードをテストすると、望ましい結果 696 が得られることがわかります。

再帰的な解決策

再帰は、メソッドがそれ自体を呼び出すときに発生します。このような方法を再帰的方法と呼びます。原則として、次の 2 つの部分で構成されます。
  1. 終了条件 — 終了条件が満たされると、メソッドはそれ自体の呼び出しを停止し、値の受け渡しを開始する必要があります。結局のところ、終了条件がない場合、StackOverflowErrorが発生するまでメソッドが繰り返し自身を呼び出す無限ループが発生します。
  2. 状況に応じて必要なロジックに加えて再帰呼び出しも必要ですが、入力値は異なります。
Java で階乗を求めることは、再帰を使用する場合の完璧な例です。

public static int getFactorial(int f) { // finding factorial of number using recursive solution
  if (f <= 1) {
     return 1;
  }
  else {
     return f * getFactorial(f - 1);
  }
}
再帰の終了条件は、1 に到達したときです。パラメータが 1 でない場合、メソッドへの次の再帰呼び出しの結果 (現在の値から 1 を引いたものを渡します) を現在の値に乗算します。

ストリームによるソリューション

Java の Stream 機能に詳しくない人、または記憶を新たにしたい人は、ここを読むと役に立ちます。

public static int getFactorial(int f) { // finding factorial of number using Stream 
  if (f <= 1) {
     return 1;
  }
  else {
     return IntStream.rangeClosed(2, f).reduce((x, y) -> x * y).getAsInt();
  }
}
ここでは特別なIntStreamクラスを使用します。これにより、int 値のストリームを操作するときに追加機能が提供されます。このようなストリームを作成するには、静的なrangeClosedメソッドを使用します。このメソッドは、2 から f までの値を 1 ずつ増分して生成します。次に、reduce メソッドを使用してすべての値を結合します。より具体的には、値をどのように組み合わせたいかを示します。最後に、ターミナルのgetAsIntメソッドを使用して結果の値を取得します。

BigInteger の使用

Java では、数値、特に BIG 数値を処理するためにBigIntegerクラスがよく使用されます。実際、 intを使用する場合、データ損失なしで処理できる最大階乗は 31 です。long データ型の場合最大階乗は 39 です。しかし、100 の階乗が必要な場合はどうなるでしょうか。前のソリューションを BigInteger に適応させてみましょう。階乗用 Java プログラム - 2

通常の解決策


public static BigInteger getFactorial(int f) { // finding factorial of number using BigInteger
  BigInteger result = BigInteger.ONE;
  for (int i = 1; i <= f; i++)
     result = result.multiply(BigInteger.valueOf(i));
  return result;
}
アルゴリズムは基本的に同じですが、ここでは BigInteger の機能を使用します。BigInteger.ONEは開始値 1 で、multiply() は前の階乗値と現在の数値を乗算するために使用されます。

再帰的な解決策


public static BigInteger getFactorial(int f) {
  if (f <= 1) {
     return BigInteger.valueOf(1);
  }
  else {
     return BigInteger.valueOf(f).multiply(getFactorial(f - 1));
  }
}
BigInteger を操作するためのいくつかのメソッドが追加されることを除いて、ソリューションの一般的なロジックは変わりません。

ストリームによるソリューション


public static BigInteger getFactorial(int f) {
  if (f < 2) {
     return BigInteger.valueOf(1);
  }
  else {
     return IntStream.rangeClosed(2, f).mapToObj(BigInteger::valueOf).reduce(BigInteger::multiply).get();
  }
}
基本的にはすべて同じですが、BigInteger が異なります。Stream クラスは、mapToObjメソッドを提供します。これを使用して、int 値を BigInteger に変換し、 multiplyメソッドを使用してそれらの値を乗算します(オプションラッパーからオブジェクトを取得するためにget()が追加されました)。これら 3 つのメソッドのいずれかを引数 100 で実行すると、スタック オーバーフローが回避され、正しい結果が得られます。
9332621544394415268169923885626670049071596826438162146859296389521759999322991560894146397615651828625369792082722375825 1185210916864000000000000000000000000
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION