【问题标题】:Factorials Challenge.(Beginner's Challenge)阶乘挑战。(初学者挑战)
【发布时间】:2018-04-14 06:44:06
【问题描述】:

我尝试了以下挑战:

鉴于前几个阶乘:

1! = 1

2! = 2 x 1 = 2

3! = 3 x 2 x 1 = 6

4! = 4 x 3 x 2 x 1 = 24

前 15 个阶乘的总和是多少,不包括 0!?

我在 Java 中的解决方案如下:

public class Factorial
{
   public static void main(String[] args)
   {
     int sum = 0;    
     int multi = 1;
        for (int i=1;i<=15;i++)         
        {
        multi = multi*i;
        sum = multi+sum;     
        }     
     System.out.print(sum);
   }
}

我验证了前 7 个阶乘的解决方案,但它适用于前 15 个吗?

【问题讨论】:

  • 提示:对于一个优雅的解决方案 - 使用递归方法。
  • @Che 对于表现不佳的解决方案,请使用递归方法
  • @CheJami 递归阶乘并不优雅。它实际上是您可以编写的最糟糕的递归函数。它适用于较小的数字,但不适用于较大的数字,并且阶乘呈指数增长,因此阶乘实际上适用的数字集非常非常小。
  • 递归阶乘并不像这些 cmets 所表明的那么糟糕。它可以以 O(n) 的时间和内存复杂度来完成。迭代解决方案的内存使用量为 O(1),时间复杂度为 O(n)。我想知道人们是否在考虑递归斐波那契数列计算,这是递归算法性能不佳的教科书示例。
  • 不建议在 Java 中使用递归解决方案,但在使用尾递归优化(如 Scheme 或其他一些函数)的语言中使用递归是很疯狂的编程语言。问题不是递归,而是语言和实现。

标签: java math factorial


【解决方案1】:

由于integer overflow,它不适用于前 15 个阶乘。正确答案是1401602636313,它超出了Java 的int 界限2147483647。您可以使用界限为9223372036854775807 的longBigInteger

【讨论】:

  • 是的,它适用于 long,我忘记了这个溢出。我找到了相同的答案:1401602636313。
【解决方案2】:

不,它不能工作 15。使用长。此外,您可以在循环内移动 print 语句,以检查它从哪里开始失败。我猜在这种情况下是 13。

【讨论】:

  • 它从 13 号开始失败,它的工作很长。
【解决方案3】:

那个

public static void printFactorials (int max) {
    long fac = 1;
    long sum = 0;
    for (int i = 1; i <= max; fac *= ++i) {
        System.out.println(String.format("Factorial(%2d)=%d", i, fac));
        sum += fac;
    }
    System.out.println(String.format("Sum of Factorials(1 to %2d)=%d", max, sum));
}

给你

Factorial( 1)=1
Factorial( 2)=2
Factorial( 3)=6
Factorial( 4)=24
Factorial( 5)=120
Factorial( 6)=720
Factorial( 7)=5040
Factorial( 8)=40320
Factorial( 9)=362880
Factorial(10)=3628800
Factorial(11)=39916800
Factorial(12)=479001600
Factorial(13)=6227020800
Factorial(14)=87178291200
Factorial(15)=1307674368000
Sum of Factorials(1 to 15)=1401602636313

long 21 开始失败,下一步是BigInteger

public static void printRlyBigFactorials (int max) {
    BigInteger fac = BigInteger.ONE;
    BigInteger sum = BigInteger.ZERO;
    for (int i = 1; i <= max; ++i) {
        fac = fac.multiply(BigInteger.valueOf(i));
        sum = sum.add(fac);
        System.out.println(String.format("Factorial(%2d)=%d", i, fac));
    }
    System.out.println(String.format("Sum of Factorials(1 to %2d)=%d", max, sum));
}

这几乎可以无限期地发挥作用,并且可以为您提供精美的结果,例如:

Sum of Factorials(1 to 500)=
1222581999810786173488382263893486121736784649845260488587055662127413631697
9142090995417259894466676137016242713788312106218384177808117660024733369428
7060019503701220190523381023699528466605036804597249531428694859689049295904
5138704466475196055082304091214424335155644013903958356823605973150159110295
5787828433482529258832635575855564789877227459384652114477297831606218655683
9245588828671235437927278554210732477499719243692398907465554636521289870187
5799458234466791378320221140358905721655475503366304295011345436395868843079
5463780536087239619245051615759218253091986494512882003123090598805090122753
7135918455294416676103707115038417384516670399033063650562275830354903359872
0775172343137459008549361297203752431405977559950082400276439557196120290170
5516606073135650288107937474531851451830365876392678959480905477335825506233
3795849463603798966643420966668878072957663827751761832039623225350606860709
6479320263132522604054741925038640750661849690108363701190203548476572823422
7743271977187818002695582046473911765828511673121820261887951566200568565033
40092247479478684738621107994804323593105039052556442336528920420940313

【讨论】:

  • 没错。整数溢出是我使用 int 而不是 long 的错误。