有没有一种方法可以计算Java中的阶乘?

98 java

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

Bil*_*ard 58

Apache Commons MathMathUtils类中有一些阶乘方法.

  • ArithmeticUtils.factorial现在显然已被弃用,atm使用[CombinatoricsUtils.factorial](https://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/CombinatoricsUtils.html#factorial( INT)) (4认同)
  • 它目前在 ArithmeticUtils 中。 (3认同)

小智 40

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

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

        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 但是这个解决方案只适用于少数人 (5认同)
  • 大数字版本:public static BigInteger factorial(BigInteger n){BigInteger factorial = BigInteger.valueOf(1); for(int i = 1; i <= n.intValue(); i ++){factorial = factorial.multiply(BigInteger.valueOf(i)); 返回阶乘; } (2认同)

Kar*_*gan 23

我不认为为factorial提供库函数会有用.对有效的因子实现进行了大量研究.这是一些实现.

  • 为什么为factorial提供库函数没用? (173认同)
  • 在实际代码中实际上并不需要很多人.如果你这样做,那么你可能正在做一些高级数学或统计,在这种情况下,你很可能已经使用了具有专门的因子实现的数学库. (13认同)
  • 超出该链接的代码不是java FYI. (4认同)
  • gamma 函数非常有用,这就是它包含在 C++ 标准库中的原因。 (3认同)
  • 在我看来,@KarlthePagan 意味着拥有一个 _standard_ 库函数用于阶乘是没有用的——对吗? (2认同)

Igo*_*kon 22

在实践中很少需要裸露的裸体因子.大多数情况下,您将需要以下之一:

1)将一个因子除以另一个因子,或

2)近似浮点答案.

在这两种情况下,您都可以使用简单的自定义解决方案.

在情况(1)中,例如,如果x = 90!/ 85!,然后你将计算结果就像x = 86*87*88*89*90,而不需要保持90!在记忆中 :)

在情况(2)中,谷歌为"斯特林的近似".

  • 反例:计算带有N个元素的排列数仅需阶乘,如果要分配一个结构来保存排列,则需要此因数。 (3认同)

dog*_*ane 12

使用番石榴BigIntegerMath如下:

BigInteger factorial = BigIntegerMath.factorial(n);
Run Code Online (Sandbox Code Playgroud)

(对于类似的功能intlong是在可用的IntMathLongMath分别).


Val*_*her 6

Apache Commons Math包有一个阶乘方法,我想你可以使用它.


Fer*_*eri 6

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

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 递归函数是很好的,但如果有人会尝试计算一个非常大的fatiorial,他们将最终得到StackOverflowException;)+我不确定,但我认为递归比旧的循环方法慢;) (4认同)
  • 那很简单。每个递归地将当前位置放在堆栈上,因此程序将有“内存”的位置在方法调用完成后返回。堆栈有其局限性。要自己尝试,请尝试将上面的代码更改为 `System.out.println(calc(10));` 到 `System.out.println(calc(Long.MAX_VALUE));` 你应该得到很长的 stactrace :) (2认同)

mid*_*ite 6

我相信这将是最快的方式,通过查找表:

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];
}
Run Code Online (Sandbox Code Playgroud)

对于本机类型long(8字节),它只能容纳20!

20! = 2432902008176640000(10) = 0x 21C3 677C 82B4 0000
Run Code Online (Sandbox Code Playgroud)

显然21!会导致溢出.

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


Per*_*org 6

因为阶乘增长如此之快,如果使用递归,堆栈溢出不是问题.其实价值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);
}
Run Code Online (Sandbox Code Playgroud)

另一种(更酷)的方法是使用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);
}
Run Code Online (Sandbox Code Playgroud)

阅读使用Java 8流的Factorials的更多信息


bdo*_*lan 5

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

  • 我同意你的看法,还有更重要的数学函数.但在我看来,这种方法应该是标准的,以便人们可以重复使用它.没有必要多人实施多次.出于教育目的,可能会这样做.但是对于每天的工作而言,它已经过时了.这是我的意见.无论如何,谢谢你的回答.我会自己做 - 另一次. (6认同)
  • 不同意.[Combinatorics](http://en.wikipedia.org/wiki/Combinatorics)需要使用因子,这在软件设计的许多方面都是必需的.不包含内置数学库中的阶乘的论证与没有内置数学库的论点相同. (3认同)
  • "......每个人都知道如何编写一个因子函数"http://chaosinmotion.com/blog/?p=622 (2认同)