【问题标题】:Find factorial of large numbers in Java在Java中查找大数的阶乘
【发布时间】:2012-07-12 07:29:43
【问题描述】:

我试图找到一个大数的阶乘,例如8785856 以典型的方式使用for-loop和double数据类型。

但结果显示为无穷大,可能是因为它超出了它的限制。

所以请指导我如何找到一个非常大的数的阶乘。

我的代码:

class abc
{
    public static void main (String[]args)
    {
        double fact=1;
        for(int i=1;i<=8785856;i++)
        {
            fact=fact*i;
        }

        System.out.println(fact);
    }
}

输出:-

Infinity

我是 Java 新手,但已经学习了一些 IO 处理等概念。

【问题讨论】:

  • 你为什么不使用像BigInteger这样的更高数据类型,这也是作业吗?如果是,则标记为这样。
  • 你的循环变量 i 是 int 并且你试图在其中存储一个巨大的数字,也尝试将其设为 double
  • 根据我的计算,大约需要 25 兆字节的内存来表示这个数字。即便如此,也不会听到BigInteger 类的声音。
  • 是的,我也使用过 biginteger,但编译器无法显示这样一个数字的答案,所以还有其他出路吗???
  • “无法显示答案”是什么意思?能否贴出“无法显示答案”的代码?

标签: java factorial largenumber


【解决方案1】:
public static void main(String[] args) {
    BigInteger fact = BigInteger.valueOf(1);
    for (int i = 1; i <= 8785856; i++)
        fact = fact.multiply(BigInteger.valueOf(i));
    System.out.println(fact);
}

【讨论】:

  • 其实这个我已经试过了,但是我在等待编译器执行这个......
  • 是的,你必须这样做。它也需要大量的 jvm 内存,但我们没有替代因为阶乘数字太大!
  • 但我等了至少 30-35 分钟……但什么也没发生……下次我运行它时我应该等待时间吗???
  • 你可以增加你的jvm内存
【解决方案2】:

您可能需要重新考虑计算这个巨大的价值。 Wolfram Alpha's Approximation 表明它肯定不适合在您的主内存中显示。

【讨论】:

  • 除非我做错了计算,否则它将适合内存:log2(10^10^8) = 3.32 * 10^8 = 300M bits = 38MByte
  • 不得不说,我自己也懒得计算内存占用了。出于好奇,有人知道如果您尝试打印 38MB 的内存块会发生什么吗?
【解决方案3】:

这段代码应该可以正常工作:-

public class BigMath {
    public static String factorial(int n) {
        return factorial(n, 300);
    }

    private static String factorial(int n, int maxSize) {
        int res[] = new int[maxSize];
        res[0] = 1; // Initialize result
        int res_size = 1;

        // Apply simple factorial formula n! = 1 * 2 * 3 * 4... * n
        for (int x = 2; x <= n; x++) {
            res_size = multiply(x, res, res_size);
        }

        StringBuffer buff = new StringBuffer();
        for (int i = res_size - 1; i >= 0; i--) {
            buff.append(res[i]);
        }

        return buff.toString();
    }

    /**
     * This function multiplies x with the number represented by res[]. res_size
     * is size of res[] or number of digits in the number represented by res[].
     * This function uses simple school mathematics for multiplication.
     * 
     * This function may value of res_size and returns the new value of res_size.
     */
    private static int multiply(int x, int res[], int res_size) {
        int carry = 0; // Initialize carry.

        // One by one multiply n with individual digits of res[].
        for (int i = 0; i < res_size; i++) {
            int prod = res[i] * x + carry;
            res[i] = prod % 10; // Store last digit of 'prod' in res[]
            carry = prod / 10;  // Put rest in carry
        }

        // Put carry in res and increase result size.
        while (carry != 0) {
            res[res_size] = carry % 10;
            carry = carry / 10;
            res_size++;
        }

        return res_size;
    }

    /** Driver method. */
    public static void main(String[] args) {
        int n = 100;

        System.out.printf("Factorial %d = %s%n", n, factorial(n));
    }
}

【讨论】:

  • 这其实是一个更好的程序,效率高,不用BigInteger
  • 取自 GeeksForGeeks!
  • @YudhishthirSingh 如果您找到源链接,请为抄袭提出自定义标记。 (如果是准确的副本。)
【解决方案4】:

提示:使用BigInteger 类,并准备好给JVM 大量内存。 8785856! 的值是一个非常大的数字。

【讨论】:

  • 是的,我也使用过 biginteger,但是编译器无法显示这样一个数字的答案,所以还有其他出路吗???
  • 尝试增加堆大小。
【解决方案5】:

使用类BigInteger。 (我不确定这是否适用于如此巨大的整数)

【讨论】:

  • 是的,我也使用过 biginteger,但是编译器无法显示这样一个数字的答案,所以还有其他出路吗???
  • @HimanshuAggarwal 您可以尝试一些讨厌的事情,例如编写自己的整数乘法例程。例如,你可以用两个大整数来表示一个 HUGE 整数。好吧,这将是复杂和麻烦的。例如如果我的整数大小为 4 位,来表示像 18 这样的数字,我可以使用 2 个整数:1 和 8 并具有适当的权重。 (1 权重为 10^1,8 权重为 10^1)。因此,如果您可以编写代码来表示带有附加权重的小整数块中的大整数,并编写自己的乘法例程,就可以做到。
  • 是的……你能详细解释一下吗?
  • 在前面的评论中,8 是 10^0。对于乘法,你必须处理所有的权重等等。它会很慢。非常慢。这个概念大致基于WallaceTree
  • 好的.....但这肯定会很麻烦......顺便说一下thanx的解释......我也会尝试实现这个方法...... :-)
【解决方案6】:

InfinityDouble 类中的一个特殊保留值,当您超过 double 可以容纳的最大数量时使用。

如果您希望您的代码正常工作,请使用BigDecimal 类,但鉴于输入的数字,不要指望您的程序会很快完成执行。

【讨论】:

  • 是的,我也使用过 biginteger,但是编译器无法显示这样一个数字的答案,所以还有其他出路吗???
【解决方案7】:

使用 BigInteger 解决您的问题(8785856!)的上述解决方案实际上需要数小时的 CPU 时间,如果不是几天的话。您需要确切的结果还是一个近似值就足够了?

有一种数学方法叫做“Sterling's Approximation " 可以简单快速地计算,以下是 Gosper 的改进:

【讨论】:

    【解决方案8】:
     import java.util.*;
     import java.math.*;
    
    class main
    {
    public static void main(String args[])
    {
        Scanner sc= new Scanner(System.in);
    
            int i;
            int n=sc.nextInt();
    
    
          BigInteger fact = BigInteger.valueOf(1);
    
            for ( i = 1; i <= n; i++)
            {
                fact = fact.multiply(BigInteger.valueOf(i));
            }
            System.out.println(fact);
    
    }
    }
    

    【讨论】:

    • 我认为没有扫描仪类的答案会更好。
    【解决方案9】:

    试试这个:

    import java.math.BigInteger;
    
    public class LargeFactorial
    {
        public static void main(String[] args)
        {
            int n = 50; 
        }
        public static BigInteger factorial(int n)
        {
           BigInteger result = BigInteger.ONE;
           for (int i = 1; i <= n; i++)
               result = result.multiply(new BigInteger(i + ""));
           return result;
        }
    }
    

    【讨论】:

    • 对不起,先生,如果我的回答有误。我试图回答,以便他/她可以找到任何数字的阶乘。他/她所要做的就是改变 n 的值。
    【解决方案10】:
        Scanner r = new Scanner(System.in);
        System.out.print("Input Number : ");
        int num = r.nextInt();
        int ans = 1;
        if (num <= 0) {
            ans = 0;
        }
        while (num > 0) {
            System.out.println(num + " x ");
            ans *= num--;
        }
        System.out.println("\b\b=" + ans);
    

    【讨论】:

    • edit 你的答案并为你的代码添加简短的解释
    【解决方案11】:
        public static void main (String[] args) throws java.lang.Exception
        {
            BigInteger fact= BigInteger.ONE;
            int factorialNo = 8785856 ;
    
            for (int i = 2; i <= factorialNo; i++) {
                  fact = fact.multiply(new BigInteger(String.valueOf(i)));
            }
    
            System.out.println("Factorial of the given number is = " + fact);
         }
    

    【讨论】:

      【解决方案12】:
      import java.util.Scanner;
      
      
      public class factorial {
          public static void main(String[] args) {
              System.out.println("Enter the number : ");
              Scanner s=new Scanner(System.in);
              int n=s.nextInt();
              factorial f=new factorial();
              int result=f.fact(n);
              System.out.println("factorial of "+n+" is "+result);
          }
          int fact(int a)
          {
              if(a==1)
                  return 1;
              else
                  return a*fact(a-1);
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2021-08-11
        • 2016-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-26
        • 1970-01-01
        相关资源
        最近更新 更多