【问题标题】:Factorial in JavaJava中的阶乘
【发布时间】:2012-03-15 00:41:41
【问题描述】:

我一直在为 Java 使用这个阶乘程序:

public static long factorial(int a) {

    if(a<1) {
        return 1;
    }
    long result=1;
    long x=a;
    while(x>1) {
        result*=x;                     
        x--;
    }
    return result;
}

但是,它似乎“中断”并在 25 的阶乘之后返回一个负数。它返回一个负数一段时间然后只返回“0”。

我做错了什么导致了这个吗?

【问题讨论】:

标签: java factorial


【解决方案1】:

你已经溢出了long
请改用BigInteger

【讨论】:

  • 不错的页面,不过让我头晕目眩!
  • 我在使用 BigIntegers 时遇到了一些问题,我可以在返回之前将 long 转换为 BigInteger 吗?
  • @Toby - 不,不是long result;,而是BigInteger result; ,你的乘法看起来像这样:result = result.multiply(BigInteger.valueOf(x));
【解决方案2】:

25! = 15511210043330985984000000

Java 中 long 的最大值为2^63-1 = 9223372036854775807 (source)。

25!大约是 Java 中 long 可以存储的最大值的 1.7*10^6。请改用BigInteger

【讨论】:

    【解决方案3】:

    25!大于Long.MAX_VALUE...

    【讨论】:

      【解决方案4】:

      根据 JLS,上溢(和下溢)是无声的,这就是为什么您的结果是“惊喜”。

      你有两个选择:

      • 如果需要准确的答案,请使用 BigInteger
      • 如果不需要精确,请使用double(尽管即使这样也会溢出170!

      【讨论】:

        【解决方案5】:

        另一种不那么天真且适用于非整数的方法是使用伽马函数的自然对数。

        http://www.iro.umontreal.ca/~simardr/ssj/doc/html/umontreal/iro/lecuyer/util/Num.html

        如果您必须坚持使用此实现,我建议您研究 memoization。为什么要不断重新计算值?一旦你有了一个,就挂在它上面,然后在重复请求时分发它。

        【讨论】:

        • 那无济于事;它仍然会溢出。
        • 最终,但双倍会比长会更久。自然对数也会延迟它。有助于组合计算:只需添加和减去自然对数。
        【解决方案6】:

        查看http://en.wikipedia.org/wiki/Integer_overflow,我知道标题指的是整数,但原理代表 int、long、double 等。

        简而言之,原始数据类型有一个最大值,当你超过它时,它会环绕并重新开始。如果你真的想对它有所了解,请学习二进制加法以完全理解它。

        【讨论】:

          【解决方案7】:

          以下是您所缺少的:当有符号整数基本类型(例如 short、int、long)在其可以表示的有符号值之上递增时,它会尝试翻转其符号位,即最左边的位,这应该只用于指示数字的符号。符号位中的 1 表示负值。这种现象称为整数溢出。

          考虑一个虚构的 3 位有符号原始数据类型(为了比较,Java long 是 64 位)。它可以表示 -4 到 3 之间的数字。

          3,3位数字所能表示的最大正值,如下所示:011

          011加1得到:100(数字部分溢出到符号部分)

          100 的十进制版本是 -4

          但是,当您开始处理 long 的容量时,需要计算很多位数,因此这里有一个快速的方法来确定给定非递减序列(在本例中为阶乘)定义的最大数字:

          long n = 1;
          while (factorial(n) > 0) {
              System.out.println("factorial of " + n++ + " can fit in a long!");
          }
          

          这看起来应该是一个无限循环,但事实并非如此;最终,由于整数溢出,factorial(n) 将返回负数。 这将为您提供以下输出:

          factorial of 1 can fit in a long!
          factorial of 2 can fit in a long!
          factorial of 3 can fit in a long!
          factorial of 4 can fit in a long!
          factorial of 5 can fit in a long!
          factorial of 6 can fit in a long!
          factorial of 7 can fit in a long!
          factorial of 8 can fit in a long!
          factorial of 9 can fit in a long!
          factorial of 10 can fit in a long!
          factorial of 11 can fit in a long!
          factorial of 12 can fit in a long!
          factorial of 13 can fit in a long!
          factorial of 14 can fit in a long!
          factorial of 15 can fit in a long!
          factorial of 16 can fit in a long!
          factorial of 17 can fit in a long!
          factorial of 18 can fit in a long!
          factorial of 19 can fit in a long!
          factorial of 20 can fit in a long!
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-01-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-03-24
            • 2012-01-01
            相关资源
            最近更新 更多