在 Java 中有没有计算阶乘的方法?

我还没找到,我错过什么了吗? 我知道阶乘方法是初学者常用的示例程序。但是有一个标准的实现来重用这个实现不是很有用吗? 我可以对标准类型(Eg.int,long...)和 BigInteger/BigDecimal 使用这种方法。

369326 次浏览

虽然阶乘对于初学者来说是一个很好的练习,但是在大多数情况下它们不是非常 useful,而且每个人都知道如何编写阶乘函数,所以它们通常不在普通的库中。

I don't think it would be useful to have a library function for factorial. There is a good deal of research into efficient factorial implementations. Here is a handful of implementations.

在实践中很少需要裸阶乘。通常你需要以下的一种:

1) divide one factorial by another, or

2)近似浮点数答案。

在这两种情况下,您最好使用简单的自定义解决方案。

假设(1) ,假设 x = 90!/85!,然后您将计算结果正如 x = 86 * 87 * 88 * 89 * 90,而不需要保持90!回忆:)

在情况(2)中,用 google 搜索“ Stirling 近似”。

The only business use for a factorial that I can think of is the Erlang B and Erlang C formulas, and not everyone works in a call center or for the phone company. A feature's usefulness for business seems to often dictate what shows up in a language - look at all the data handling, XML, and web functions in the major languages.

对于类似这样的东西,很容易保留一个阶乘代码片段或库函数。

Apache Commons Math has a few factorial methods in the 数学工具 class.

Apache Commons Math 包有 阶乘法阶乘法,我想你可以使用它。

public class UsefulMethods {
public static long factorial(int number) {
long result = 1;


for (int factor = 2; factor <= number; factor++) {
result *= factor;
}


return result;
}
}

Big Numbers version by HoldOffHunger:

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

使用番石榴的 BigIntegerMath如下:

BigInteger factorial = BigIntegerMath.factorial(n);

(intlong的类似功能分别在 IntMathLongMath中提供。)

简短的回答是: 使用递归。

您可以创建一个方法并在同一个方法中递归地调用该方法:

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

对于本机类型 long(8字节) ,它只能保持到 20!

20! = 2432902008176640000(10) = 0x 21C3 677C 82B4 0000

显然,21!会导致溢出。

因此,对于本机类型 long,只允许最大值的 20!,这是有意义的,并且是正确的。

计算阶乘的一个非常简单的方法:

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 等等。

附言。这可能不是最好的解决方案,但我是编程新手,我花了很长时间才找到一个简单的代码,可以计算阶乘,所以我不得不自己写的方法,但我把这个放在这里,所以它可以帮助其他人喜欢我。

也可以使用递归版本。

static int myFactorial(int i) {
if(i == 1)
return;
else
System.out.prinln(i * (myFactorial(--i)));
}

Recursion is usually less efficient because of having to push and pop recursions, so iteration is quicker. On the other hand, recursive versions use fewer or no local variables which is advantage.

public static int fact(int i){
if(i==0)
return 0;
if(i>1){
i = i * fact(--i);
}


return i;
}

Factorial 是一个高度增长的离散函数,所以我认为使用 BigInteger 比使用 int 更好。 I have implemented following code for calculation of factorial of non-negative integers.I have used recursion in place of using a loop.

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"))));
}

Here the range of big integer is

-2^Integer.MAX_VALUE (exclusive) to +2^Integer.MAX_VALUE,
where Integer.MAX_VALUE=2^31.

但是,通过使用无符号 BigInteger,可以将上面给出的 factorial 方法的范围扩展两次。

我们需要迭代地实现。如果我们递归地实现,如果输入变得非常大(即20亿) ,它将导致 StackOverflow。而且我们需要使用未绑定的大小数字,比如 BigInteger,以避免当阶乘数字大于给定类型的最大数字时发生算术溢出(例如,对于 int 类型,20亿)。可以使用 int 表示 factorial 的最大值为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;
}

Because factorial grows so quickly, stack overflow is not an issue if you use recursion. In fact, the value of 20! is the largest one can represent in a Java long. So the following method will either calculate factorial(n) or throw an IllegalArgumentException if n is too big.

public long factorial(int n) {
if (n > 20) throw new IllegalArgumentException(n + " is out of range");
return (1 > n) ? 1 : n * factorial(n - 1);
}

做同样事情的另一种(更酷的)方法是像下面这样使用 Java8的流程库:

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

阅读更多 使用 Java8流的阶乘

我发现了一个惊人的技巧,可以在实际的乘法中找到一半的阶乘。

请耐心等待,因为这是一个有点长的职位。

偶数: 要用偶数将乘法减半,最后得到的是 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

很简单,不是吗?)

现在对于奇数: 如果数字是奇数,加法是相同的,就像你每次减去两个,但是你停在三个。然而,因素的数量发生了变化。如果你把这个数除以2,你会得到一个以5结尾的数。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是一个声明为 static 的布尔变量; 它用于第一种情况,在这种情况下我们不想更改前一个和。

试试偶数和奇数。

试试这个

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

我们只有一条线来计算:

Long factorialNumber = LongStream.rangeClosed(2, N).reduce(1, Math::multiplyExact);
public int factorial(int num) {
if (num == 1) return 1;
return num * factorial(num - 1);
}

一个相当简单的方法

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

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

可以使用递归。

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));

我从 EDX 得到这个用它! 它叫做递归

   public static int factorial(int n) {
if (n == 1) {
return 1;
} else {
return n * factorial(n-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 code:

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

using recursion is the simplest method. if we want to find the factorial of N,我们必须考虑两种情况,其中 N = 1,N > 1,因为在阶乘中 我们继续乘 N,N-1,N-2,,,,直到1,如果我们去 N = 0,我们将得到0 为了阻止阶乘达到零,下面是 recursive method is used. Inside the factorial function,while N>1, the return 值与另一个阶乘函数的起始值相乘 将保持代码递归地调用 factorial () ,直到它到达 对于 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;
}

public static long factorial(int number) {
if (number < 0) {
throw new ArithmeticException(number + " is negative");
}
long fact = 1;
for (int i = 1; i <= number; ++i) {
fact *= i;
}
return fact;
}


使用递归。


public static long factorial(int number) {
if (number < 0) {
throw new ArithmeticException(number + " is negative");
}
return number == 0 || number == 1 ? 1 : number * factorial(number - 1);
}


source

使用 Java9 + ,您可以使用这个解决方案。

...
import java.math.BigInteger;
import java.util.stream.Stream;
...


String getFactorial(int n) {
return Stream.iterate(BigInteger.ONE, i -> i.add(BigInteger.ONE)).parallel()
.limit(n).reduce(BigInteger.ONE, BigInteger::multiply).toString();
}