有没有一种方法可以计算Java中的阶乘?
我还没有find它。 我错过了什么? 我知道一个阶乘方法是初学者常用的一个例子程序。 但是为了重用这个标准的实现是不是有用呢? 我可以使用标准types(int,long …)和BigInteger / BigDecimal这样的方法。
我不认为有一个图书馆的因子函数是有用的。 对于有效的因子实现有很多研究。 这里有一些实现。
Apache Commons Math在MathUtils类中有几个因子方法。
public class UsefulMethods { public static int factorial(int n) { if (n == 0) { return 1; } int fact = 1; // this will be the result for (int i = 1; i <= n; i++) { fact *= i; } return fact; } }
HoldOffHunger的大数字版本:
public static BigInteger factorial(BigInteger n) { BigInteger factorial = BigInteger.valueOf(1); if (n.equals(BigInteger.valueOf(0))) { return factorial; } for (int i = 1; i <= n.intValue(); i++) { factorial = factorial.multiply(BigInteger.valueOf(i)); } return factorial; }
在实践中很less需要裸裸因子。 大多数情况下,您将需要以下其中一项:
1)将一个因子除以另一个,或者
2)近似浮点回答。
在这两种情况下,使用简单的自定义解决scheme都会更好。
在(1)的情况下,如果x = 90! / 85 !,那么你就可以计算出结果,就像x = 86 * 87 * 88 * 89 * 90,而不需要保持90! 在记忆中 :)
在(2)的情况下,谷歌“斯特林的逼近”。
使用番石榴的BigIntegerMath
如下:
BigInteger factorial = BigIntegerMath.factorial(n);
( int
和long
类似function分别在IntMath
和LongMath
可用。)
尽pipe阶乘对于开始的程序员来说是一个很好的练习,但是在大多数情况下它们并不是很有用 ,而且每个人都知道如何编写一个阶乘函数,所以他们通常不在普通的库中。
简单的答案是:使用recursion。
您可以创build一个方法,然后在同一个方法中recursion地调用该方法:
public class factorial { public static void main(String[] args) { System.out.println(calc(10)); } public static long calc(long n) { if (n <= 1) return 1; else return n * calc(n - 1); } }
我相信这将是最快的方式,通过查找表:
private static final long[] FACTORIAL_TABLE = initFactorialTable(); private static long[] initFactorialTable() { final long[] factorialTable = new long[21]; factorialTable[0] = 1; for (int i=1; i<factorialTable.length; i++) factorialTable[i] = factorialTable[i-1] * i; return factorialTable; } /** * Actually, even for {@code long}, it works only until 20 inclusively. */ public static long factorial(final int n) { if ((n < 0) || (n > 20)) throw new OutOfRangeException("n", 0, 20); return FACTORIAL_TABLE[n]; }
对于本地typeslong
(8字节),它只能容纳20!
20! = 2432902008176640000(10) = 0x 21C3 677C 82B4 0000
显然, 21!
会造成溢出。
因此,对于原生types来说,最多只有20!
是允许的,有意义的,正确的。
因为阶乘增长得太快,所以如果使用recursion,堆栈溢出不是问题。 其实价值20呢! 是Java中可以代表的最大的一个。 因此,如果n太大,以下方法将计算factorial(n)或抛出IllegalArgumentException。
public long factorial(int n) { if (n > 20) throw new IllegalArgumentException(n + " is out of range"); return (1 > n) ? 1 : n * factorial(n - 1); }
另一种(更酷)的方式来做同样的事情是使用Java 8的stream库如下:
public long factorial(int n) { if (n > 20) throw new IllegalArgumentException(n + " is out of range"); return LongStream.rangeClosed(1, n).reduce(1, (a, b) -> a * b); }
使用Java 8的stream阅读更多关于分解
Apache Commons Math软件包有一个阶乘方法 ,我想你可以使用它。
尝试这个
public static BigInteger factorial(int value){ if(value < 0){ throw new IllegalArgumentException("Value must be positive"); } BigInteger result = BigInteger.ONE; for (int i = 2; i <= value; i++) { result = result.multiply(BigInteger.valueOf(i)); } return result; }
我发现了一个惊人的技巧,在实际乘法的一半中find阶乘。
请耐心等待,因为这是一个很长的职位。
对于偶数:要用偶数乘以一半,您将以n / 2因子结束。 第一个因素将是你正在采取阶乘的数量,然后下一个将是这个数字加上这个数字减去两个。 下一个数字将是前一个数字加上已经添加的数字减去两个数字。 当你添加的最后一个数字是两个(即2)时,你就完成了 。 这可能没有什么意义,所以让我举个例子。
8! = 8 * (8 + 6 = 14) * (14 + 4 = 18) * (18 + 2 = 20) 8! = 8 * 14 * 18 * 20 which is **40320**
请注意,我从8开始,然后我添加的第一个数字是6,然后是4,然后是2,每增加一个数字less于之前添加的数字两个。 这种方法相当于把最less的数字乘以最大的数字,只是乘以较less的数字,如下所示:
8! = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8! = (1 * 8) * (2 * 7) * (3 * 6) * (4 * 5) 8! = 8 * 14 * 18 * 20
简单是不是:)
现在为奇数:如果数字是奇数,加法是相同的,因为在你减去两次,但你停在三。 然而,因素的数量变化。 如果你把这个数字除以2,那么最后会有一些以.5结尾的数字。 原因是,如果我们把两个目标放在一起,我们就剩下中间的数字。 基本上,这一切都可以通过求解等于数除以二的四舍五入来解决。 如果没有math背景,这可能没有什么意义,所以让我举个例子:
9! = 9 * (9 + 7 = 16) * (16 + 5 = 21) * (21 + 3 = 24) * (roundUp(9/2) = 5) 9! = 9 * 16 * 21 * 24 * 5 = **362880**
注意:如果你不喜欢这个方法,你也可以在奇数(在这个例子中是8)之前把偶数的阶乘乘以奇数(即9!= 8!* 9)。
现在让我们用Java实现它:
public static int getFactorial(int num) { int factorial=1; int diffrennceFromActualNum=0; int previousSum=num; if(num==0) //Returning 1 as factorial if number is 0 return 1; if(num%2==0)// Checking if Number is odd or even { while(num-diffrennceFromActualNum>=2) { if(!isFirst) { previousSum=previousSum+(num-diffrennceFromActualNum); } isFirst=false; factorial*=previousSum; diffrennceFromActualNum+=2; } } else // In Odd Case (Number * getFactorial(Number-1)) { factorial=num*getFactorial(num-1); } return factorial; }
isFirst
是一个声明为静态的布尔variables; 它被用于第一种情况,我们不想改变以前的总和。
尝试偶数以及奇数。
我能想到的唯一一个阶乘的商业用途是Erlang B和Erlang C公式,并不是每个人都在呼叫中心或电话公司工作。 一个特性对业务的用处似乎常常决定了语言中显示的内容 – 查看主要语言中的所有数据处理,XML和Webfunction。
对于像这样的事情,保留一个阶乘片段或库函数是容易的。
计算阶乘的一个非常简单的方法:
private double FACT(double n) { double num = n; double total = 1; if(num != 0 | num != 1){ total = num; }else if(num == 1 | num == 0){ total = 1; } double num2; while(num > 1){ num2 = num - 1; total = total * num2; num = num - 1; } return total; }
我使用了double,因为它们可以保存大量的数字,但是你可以使用任何其他types,如int,long,float等。
PS这可能不是最好的解决scheme,但我是编程的新手,花了我很长时间才find一个简单的代码,可以计算因子,所以我必须自己写这个方法,但我把这个放在这里,所以它可以帮助像我这样的人。
您也可以使用recursion版本。
static int myFactorial(int i) { if(i == 1) return; else System.out.prinln(i * (myFactorial(--i))); }
recursion通常效率较低,因为必须推送和popuprecursion,所以迭代更快。 另一方面,recursion版本使用较less或没有局部variables,这是有利的。
因子高度增加离散函数。所以我认为使用BigInteger比使用int更好。 我已经实现了用于计算非负整数的阶乘的以下代码。我已经使用recursion来代替使用循环。
public BigInteger factorial(BigInteger x){ if(x.compareTo(new BigInteger("1"))==0||x.compareTo(new BigInteger("0"))==0) return new BigInteger("1"); else return x.multiply(factorial(x.subtract(new BigInteger("1")))); }
这里大整数的范围是
-2^Integer.MAX_VALUE (exclusive) to +2^Integer.MAX_VALUE, where Integer.MAX_VALUE=2^31.
然而,上面给出的阶乘方法的范围可以通过使用无符号的BigInteger扩展到两倍。
我们有一条线来计算它:
Long factorialNumber = LongStream.rangeClosed(2, N).reduce(1, Math::multiplyExact);
一个相当简单的方法
for ( int i = 1; i < n ; i++ ) { answer = answer * i; }
/** import java liberary class */ import java.util.Scanner; /* class to find factorial of a number */ public class factorial { public static void main(String[] args) { // scanner method for read keayboard values Scanner factor= new Scanner(System.in); int n; double total = 1; double sum= 1; System.out.println("\nPlease enter an integer: "); n = factor.nextInt(); // evaluvate the integer is greater than zero and calculate factorial if(n==0) { System.out.println(" Factorial of 0 is 1"); } else if (n>0) { System.out.println("\nThe factorial of " + n + " is " ); System.out.print(n); for(int i=1;i<n;i++) { do // do while loop for display each integer in the factorial { System.out.print("*"+(ni) ); } while ( n == 1); total = total * i; } // calculate factorial sum= total * n; // display sum of factorial System.out.println("\n\nThe "+ n +" Factorial is : "+" "+ sum); } // display invalid entry, if enter a value less than zero else { System.out.println("\nInvalid entry!!"); }System.exit(0); } }
你可以使用recursion。
public static int factorial(int n){ if (n == 0) return 1; else return(n * factorial(n-1)); }
然后在创build上面的方法(函数)之后:
System.out.println(factorial(number of your choice)); //direct example System.out.println(factorial(3));
public static int fact(int i){ if(i==0) return 0; if(i>1){ i = i * fact(--i); } return i; }
我们需要迭代实现。 如果我们recursion实现,如果input变得非常大(即2亿亿),将会导致StackOverflow。 而且我们需要使用BigInteger这样的未绑定的大小数来避免当一个阶乘数大于给定types的最大数时(即int为20亿)的算术溢出。 在溢出之前,可以使用int作为factorial的最大值14,long可以使用int的最大值20。
public BigInteger getFactorialIteratively(BigInteger input) { if (input.compareTo(BigInteger.ZERO) <= 0) { throw new IllegalArgumentException("zero or negatives are not allowed"); } BigInteger result = BigInteger.ONE; for (BigInteger i = BigInteger.ONE; i.compareTo(input) <= 0; i = i.add(BigInteger.ONE)) { result = result.multiply(i); } return result; }
如果您不能使用BigInteger,请添加错误检查。
public long getFactorialIteratively(long input) { if (input <= 0) { throw new IllegalArgumentException("zero or negatives are not allowed"); } else if (input == 1) { return 1; } long prev = 1; long result = 0; for (long i = 2; i <= input; i++) { result = prev * i; if (result / prev != i) { // check if result holds the definition of factorial // arithmatic overflow, error out throw new RuntimeException("value "+i+" is too big to calculate a factorial, prev:"+prev+", current:"+result); } prev = result; } return result; }
public int factorial(int num) { if (num == 1) return 1; return num * factorial(num - 1); }
while循环(小数字)
public class factorial { public static void main(String[] args) { int counter=1, sum=1; while (counter<=10) { sum=sum*counter; counter++; } System.out.println("Factorial of 10 is " +sum); } }
我从EDX得到这个使用它! 它被称为recursion
public static int factorial(int n) { if (n == 1) { return 1; } else { return n * factorial(n-1); } }