Java 在32位机器中高效地计算阶乘

Java 在32位机器中高效地计算阶乘,java,performance,factorial,Java,Performance,Factorial,如何实现一个函数,以便在给定一个数字的情况下计算阶乘。给定的数字将是一个大数字(例如100!),我不想使用java.math库 谢谢 您可以计算的最大阶乘,并且仍然适合于有符号32位整数是12 对于适合32位整数的阶乘,可以使用任何算法。事实上,您甚至可以这样查找它们以获得最佳性能 像这样 private static int factorial(int n) { final int f[] = { 1, 2, 6, 24, 120, 720, 5040, 40320,

如何实现一个函数,以便在给定一个数字的情况下计算阶乘。给定的数字将是一个大数字(例如100!),我不想使用java.math库

谢谢

  • 您可以计算的最大阶乘,并且仍然适合于有符号32位整数是12

  • 对于适合32位整数的阶乘,可以使用任何算法。事实上,您甚至可以这样查找它们以获得最佳性能

  • 像这样

    private static int factorial(int n) {
        final int f[] = {
            1, 2, 6, 24, 120, 720, 5040, 40320,
            362880, 3628800, 39916800, 479001600
        };
        if (n < 1 || n > f.length+1)
            throw new IllegalArgumentException("n");
        return f[n-1];
    }
    
    私有静态整数阶乘(int n){
    最终整数f[]={
    1, 2, 6, 24, 120, 720, 5040, 40320,
    362880, 3628800, 39916800, 479001600
    };
    如果(n<1 | | n>f.长度+1)
    抛出新的IllegalArgumentException(“n”);
    返回f[n-1];
    }
    
    使用32位整数时,无论是有符号还是无符号,可以表示的最大阶乘是12=479001600考虑到内存便宜,一个有效的实现是查找表:

    static final int [] FACTORIALS =
        {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880,
         3628800, 39916800, 479001600 };
    
    int factorial(int n) {
        return FACTORIALS[n];
    }
    
    当然,您应该在此处为
    n
    添加一些范围检查


    对于较大的阶乘,请使用
    biginger

    它实际上取决于输出到的数据类型。记住,重要的不是机器使用的位数——即使在32位机器上,Java
    long
    也将是64位

    如果要输出到
    int
    long
    ,最快的方法就是拥有一个正确阶乘值的静态常量数组,并在那里查找答案。这是最便宜的了。您可以手动输入这些常量,也可以写入

    static final int[] factorials = {
       1,
       1,
       1 * 2,
       1 * 2 * 3,
       1 * 2 * 3 * 4,
       ...,
       1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12};
    
    …编译器将在编译时为您计算这些值

    如果您想输出到一个
    biginger
    …那就有点有趣了。番石榴在这里做了一些有趣的事情;您可以使用它或尝试自己重新实现它。从1到n,它

    • 计算出2的幂,特别计算它们在最后被移回
    • 将数字相乘,直到它们将溢出
      long
      ,然后将结果转换为
      BigInteger
      ,并将其添加到列表中
    • 分而治之——如果列表有四个元素,a,b,c,d,它会执行
      (a*b)*(c*d)
      ,所以它会将列表一分为二,递归相乘,然后将结果相乘
    • 最后以2的幂的形式返回

    关于
    如何
    你问题的一部分,我有两个简单的解决办法1。使用一个简单的循环,例如阶乘(3),将数字3、2和1相乘。二,。使用递归函数。如果效率是最重要的,请下载大量预先计算的值并创建一个查找表。最大值当然取决于您是想要
    短阶乘(int x)
    整数阶乘(int x)
    长阶乘(int x)
    还是
    大整数阶乘(int x)
    。32位机器的Java代码与64位机器的Java代码相同。您的限制是可以寻址的内存量。如何优化代码取决于您的上下文;i、 e.为什么要这样做。通常阶乘被用作更大计算的一部分,如何优化它取决于它的使用方式;我不希望Java像其他语言一样在不同的运行中共享它。@LouisWasserman:是的,光是
    final
    是不行的。已更改代码。您的查找表不正确--您得到13!错了——更重要的是,13!不适合32位有符号整数。是的,我已经更新了。