Answers:
Apache Commons Math在MathUtils类中有一些析因方法。
public class UsefulMethods {
public static long factorial(int number) {
long result = 1;
for (int factor = 2; factor <= number; factor++) {
result *= factor;
}
return result;
}
}
HoldOffHunger的 Big Numbers版本:
public static BigInteger factorial(BigInteger number) {
BigInteger result = BigInteger.valueOf(1);
for (long factor = 2; factor <= number.longValue(); factor++) {
result = result.multiply(BigInteger.valueOf(factor));
}
return result;
}
在实践中几乎不需要裸露阶乘。通常,您将需要以下之一:
1)将一个阶乘除以另一个,或
2)近似浮点答案。
在这两种情况下,使用简单的自定义解决方案都会更好。
在情况(1)中,假设x = 90!/ 85 !,那么您将计算出x = 86 * 87 * 88 * 89 * 90的结果,而无需保持90!在记忆中 :)
在情况(2)中,用Google搜索“斯特林近似值”。
使用番石榴BigIntegerMath如下:
BigInteger factorial = BigIntegerMath.factorial(n);
尽管阶乘对于初学者来说是一个很好的练习,但是在大多数情况下它们并不是很有用,而且每个人都知道如何编写阶乘函数,因此它们通常不在普通库中。
我相信通过查找表,这将是最快的方法:
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];
}
对于本机类型long(8个字节),它最多只能容纳20!
20! = 2432902008176640000(10) = 0x 21C3 677C 82B4 0000
显然,21!会引起溢出。
因此,对于本机类型long,仅20!允许最大数量,有意义和正确的。
因为阶乘增长如此之快,所以如果您使用递归,堆栈溢出就不会成为问题。其实值20!是Java long中最大的代表。因此,如果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的流库,如下所示:
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流的阶乘的更多信息
简短的答案是:使用递归。
您可以创建一个方法,然后在同一方法内递归调用该方法:
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);
}
}
System.out.println(calc(10));以System.out.println(calc(Long.MAX_VALUE));你应该会很长stactrace :)
BigInteger。我试图计算数字的阶乘,8020这使我的结果613578884952214809325384...具有27831小数位。因此,即使处理数字,也Stackoverflow不会抛出巨大的错误。当然,您说得对,但我怀疑实际使用中的数字是否很大:-)
试试这个
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;
}
i <= value。for循环可以稍微优化为(int i = 2; i <= value; i++)。
我发现了一个惊人的技巧,可以在一半的实际乘法中找到阶乘。
请耐心等待,因为这是一个漫长的过程。
对于偶数: 要使偶数减半,您将得到n / 2个因子。第一个因素将是您要提取的阶乘的数字,然后第二个因素将是该数字加上该数字减去2。下一个数字将是前一个数字加上最后添加的数字减去2。当您添加的最后一个数字为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,每个添加的数字比之前添加的数字少两个。此方法等效于用最小的数乘以最大的数,而乘以较少的乘数,如下所示:
8! = 1 * 2 * 3 * 4 * 5 * 6 * 7 *
8! = (1 * 8) * (2 * 7) * (3 * 6) * (4 * 5)
8! = 8 * 14 * 18 * 20
是不是很简单:)
现在,对于奇数:如果数字是奇数,则加法是相同的,就像您每次都减去两个一样,但是停在三个位置。但是,因素的数量会发生变化。如果将数字除以二,最终将得到以.5结尾的数字。原因是,如果我们将两端相乘,则剩下中间的数字。基本上,所有这些都可以通过求解等于四舍五入的因子来解决。没有数学背景的人,这对大脑也可能没有多大意义,所以让我举一个例子:
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是一个声明为静态的布尔变量;它用于第一种情况,我们不想更改先前的总和。
尝试使用偶数和奇数。
您可以使用递归。
public static int factorial(int n){
if (n == 0)
return 1;
else
return(n * factorial(n-1));
}
然后创建上面的方法(函数)后:
System.out.println(factorial(number of your choice));
//direct example
System.out.println(factorial(3));
一种计算阶乘的非常简单的方法:
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是因为它们可以容纳大量数字,但是您可以使用其他任何类型,例如int,long,float等。
PS:这可能不是最好的解决方案,但是我是编码的新手,花了我很多年才能找到一个可以计算阶乘的简单代码,所以我不得不自己编写方法,但是我将其放在此处,以帮助其他像我这样的人。
阶乘是离散函数的高度增加,因此我认为使用BigInteger比使用int更好。我已经实现了以下代码,用于计算非负整数的阶乘。
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("*"+(n-i) );
}
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);
}
}
public static int fact(int i){
if(i==0)
return 0;
if(i>1){
i = i * fact(--i);
}
return i;
}
我们需要迭代实现。如果我们递归实现,那么如果输入很大(即20亿),它将导致StackOverflow。而且,当阶乘数变得大于给定类型的最大数(即int为20亿)时,我们需要使用BigInteger之类的未绑定大小数来避免算术溢出。溢出之前,可以将int用于最多14个阶乘,将long用于最多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);
}
递归:
public static int factorial(int n)
{
if(n == 1)
{
return 1;
}
return n * factorial(n-1);
}
使用while循环:
public static int factorial1(int n)
{
int fact=1;
while(n>=1)
{
fact=fact*n;
n--;
}
return fact;
}
使用动态编程非常有效
如果您想使用它来一次又一次地计算(例如缓存)
Java代码:
int fact[]=new int[n+1]; //n is the required number you want to find factorial for.
int factorial(int num)
{
if(num==0){
fact[num]=1;
return fact[num];
}
else
fact[num]=(num)*factorial(num-1);
return fact[num];
}
使用递归是最简单的方法。如果要查找N的阶乘,则必须考虑N = 1和N> 1的两种情况,因为在阶乘中,我们一直将N,N-1,N-2 ,,,,,乘以1。转到N = 0,我们将得到0的答案。为了使阶乘停止为零,使用了以下递归方法。在阶乘函数内部,当N> 1时,返回值将乘以阶乘函数的另一个起始值。这将使代码递归地调用factorial(),直到达到N =1。对于N = 1的情况,它将自身返回N(= 1),并且先前乘以返回N s的所有累积结果都将与N相乘。 = 1。从而给出阶乘结果。
static int factorial(int N) {
if(N > 1) {
return n * factorial(N - 1);
}
// Base Case N = 1
else {
return N;
}