如何找到正数的阶乘?


18

挑战:

编写输入正数并返回其阶乘的程序或函数

注意:这是一个询问问题。请不要认真对待问题和/或答案。更多信息在这里。每个询问问题也是一个问题,因此,票数最高的答案将获胜。



4
-1,对不起,因为我们收到了大量这些代码拖曳问题,而这并没有真正为他们增加任何新内容
Doorknob


根据官方立场,代码拖曳正在被删除这个问题的票数很多,答案很多,其中很多都投票得很高。它在民意测验中获得了超过50%的“删除”选票,但它的独特之处在于它获得了如此多的答案和投票,因此我将其锁定为具有历史意义。
门把手

Answers:


46

这是一个非常简单的数值计算问题,我们可以用斯特林近似法解决:

Stirling's approximation formula

如您所见,该公式具有平方根,我们还将需要一种近似的方法。为此,我们将选择所谓的“巴比伦方法”,因为它可以说是最简单的方法:

Babylonian method

请注意,以这种方式计算平方根是递归的一个很好的例子。

将所有内容放到Python程序中,可以为您解决以下问题:

def sqrt(x, n): # not the same n as below
    return .5 * (sqrt(x, n - 1) + x / sqrt(x, n - 1)) if n > 0 else x

n = float(raw_input())
print (n / 2.718) ** n * sqrt(2 * 3.141 * n, 10)

通过简单的修改,上述程序可以输出整洁的阶乘表:

1! =    0.92215
2! =    1.91922
3! =    5.83747
4! =   23.51371
5! =  118.06923
6! =  710.45304
7! = 4983.54173
8! = 39931.74015
9! = 359838.58817

对于大多数应用程序,此方法应足够准确。


16
+1该方法的简单性和准确性使其成为了明显的赢家
Joe the Person

44

C#

抱歉,但是我讨厌递归函数。

public string Factorial(uint n) {
    return n + "!";
}

1
从技术上讲,您已经满足了该简短要求!;)+1短暂滥用
WallyWest

36

爪哇

public int factorial ( int n ) {
switch(n){
case 0: return 1;
case 1: return 1;
case 2: return 2;
case 3: return 6;
case 4: return 24;
case 5: return 120;
case 6: return 720;
case 7: return 5040;
case 8: return 40320;
case 9: return 362880;
case 10: return 3628800;
case 11: return 39916800;
case 12: return 479001600;
default : throw new IllegalArgumentException();
}
}

16
我尝试了-非常有效。将与下一个版本一起发布。:)
约翰内斯

除了“幻数综合症”以外,只要n <13,堆栈少得多,这实际上可能是一个好的实现。写下“情况4:返回4 * 3 * 2;” 并且您将拥有一个不错的类,比旧的递归类要快得多。
Fabinout 2014年

6
@Fabinout,即使对于n> = 13,实现也是正确的。13!> Integer.MAX_VALUE。
emory

21

蟒蛇

当然,解决任何问题的最佳方法是使用正则表达式:

import re

# adapted from http://stackoverflow.com/q/15175142/1333025
def multiple_replace(dict, text):
  # Create a regular expression  from the dictionary keys
  regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
  # Repeat while any replacements are made.
  count = -1
  while count != 0:
    # For each match, look-up corresponding value in dictionary.
    (text, count) = regex.subn(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
  return text

fdict = {
    'A': '@',
    'B': 'AA',
    'C': 'BBB',
    'D': 'CCCC',
    'E': 'DDDDD',
    'F': 'EEEEEE',
    'G': 'FFFFFFF',
    'H': 'GGGGGGGG',
    'I': 'HHHHHHHHH',
    'J': 'IIIIIIIIII',
    'K': 'JJJJJJJJJJJ',
    'L': 'KKKKKKKKKKKK',
    'M': 'LLLLLLLLLLLLL',
    'N': 'MMMMMMMMMMMMMM',
    'O': 'NNNNNNNNNNNNNNN',
    'P': 'OOOOOOOOOOOOOOOO',
    'Q': 'PPPPPPPPPPPPPPPPP',
    'R': 'QQQQQQQQQQQQQQQQQQ',
    'S': 'RRRRRRRRRRRRRRRRRRR',
    'T': 'SSSSSSSSSSSSSSSSSSSS',
    'U': 'TTTTTTTTTTTTTTTTTTTTT',
    'V': 'UUUUUUUUUUUUUUUUUUUUUU',
    'W': 'VVVVVVVVVVVVVVVVVVVVVVV',
    'X': 'WWWWWWWWWWWWWWWWWWWWWWWW',
    'Y': 'XXXXXXXXXXXXXXXXXXXXXXXXX',
    'Z': 'YYYYYYYYYYYYYYYYYYYYYYYYYY'}

def fact(n):
    return len(multiple_replace(fdict, chr(64 + n)))

if __name__ == "__main__":
    print fact(7)

1
当然的确是:)
皮埃尔·阿劳德

15

哈斯克尔

短代码是有效的代码,因此请尝试此操作。

fac = length . permutations . flip take [1..]

为什么拖钓:

我会笑任何写这篇文章的编码员。低效率是美丽的。对于实际上无法编写阶乘函数的任何Haskell程序员来说,也可能难以理解。

编辑:我前不久发布了这篇文章,但我想为以后的人和看不懂Haskell的人澄清一下。

此处的代码获取数字1到n的列表,创建该列表的所有排列的列表,并返回该列表的长度。在我的机器上,大约需要20分钟才能完成13 !!然后应该花四个小时才能完成14个工作!然后两个半天共15天!除了那里的某个时刻,您的内存不足。

编辑2:实际上,由于这是Haskell,您可能不会用完内存(请参阅下面的注释)。您也许可以强迫它评估列表并将其以某种方式保存在内存中,但是我对优化(和取消优化)Haskell的了解不足,无法确切地知道如何执行此操作。


既丑陋又优雅。
PLL

1
您确定内存问题吗?在任何时候,您都需要保留在内存中:-list [1..n]。-的一个特定置换[1..n],其余置换归于thunk(中的多项式n)。-该length功能的累加器。
约翰·德沃夏克

公平点,可能实际上不是。真的没有考虑太多。我将在底部添加评论。
jgon

10

C#

由于这是一个数学问题,因此使用专门设计用于解决数学问题的应用程序进行此计算是有意义的...

步骤1:

安装MATLAB。我认为,可以进行试用,但是这个非常复杂的问题可能很重要,值得购买完整版的应用程序。

第2步:

在您的应用程序中包括MATLAB COM组件。

第三步:

public string Factorial(uint n) {
    MLApp.MLApp matlab = new MLApp.MLApp();
    return matlab.Execute(String.Format("factorial({0})", n);
}

学生的Matlab起价为100美元。专业版或站点许可证可以达到数千种。
Moshe Katz 2013年

4
Moshe Katz-有理由的理由。
Mike H.

9

C#

阶乘是较高级别的数学运算,一口气很难消化。解决此类问题的最佳解决方案是将一个大型任务分解为多个较小的任务。

现在,n!定义为1 * 2 * ... * n,因此,本质上是重复乘法,乘法只不过是重复加法。因此,考虑到这一点,以下解决了这个问题:

long Factorial(int n)
{
    if(n==0)
    {
        return 1;
    }

    Stack<long> s = new Stack<long>();
    for(var i=1;i<=n;i++)
    {
        s.Push(i);
    }
    var items = new List<long>();
    var n2 = s.Pop();
    while(s.Count >0)
    {
        var n3 = s.Pop();
        items.AddRange(FactorialPart(n2,n3));
        n2 = items.Sum();
    }
    return items.Sum()/(n-1);
}

IEnumerable<long> FactorialPart(long n1, long n2)
{
    for(var i=0;i<n2;i++){
        yield return n1;
    }
}

您有一个瓶颈通过一个CPU或内核发送所有这些消息,我想我可能已经在我的回答中解决了这个问题:-)
Paul

9
#include <math.h>

int factorial(int n)
{
    const double g = 7;
    static const double p[] = { 0.99999999999980993, 676.5203681218851,
                                -1259.1392167224028, 771.32342877765313,
                                -176.61502916214059, 12.507343278686905,
                                -0.13857109526572012, 9.9843695780195716e-6,
                                1.5056327351493116e-7 };
    double z = n - 1 + 1;
    double x = p[0];
    int i;
    for ( i = 1; i < sizeof(p)/sizeof(p[0]); ++i )
        x += p[i] / (z + i);
    return sqrt(2 * M_PI) * pow(z + g + 0.5, z + 0.5)  * exp(-z -g -0.5) * x + 0.5;
}

巨魔:

  • 一种100%正确的阶乘计算方式,完全错过了以迭代或递归方式进行计算的要点。
  • 您不知道它为什么起作用,并且无法将其推广到其他用途。
  • 与仅使用整数数学进行计算相比,成本更高。
  • z = n - 1 + 1如果您知道发生了什么,最明显的“次优”代码()实际上是自记录的。
  • 对于额外的拖钓,我应该p[]使用序列系数的递归计算来进行计算!

(这是伽玛函数Lanczos近似值


- 1 + 1这里有什么要点吗?我的编译器对其进行了优化(这不是浮点数,在这种情况下优化代码可能会很危险),因此似乎不需要它。
Konrad Borowski14年

4
@xfix:double z = n - 1是伽马函数近似值的一部分。的+ 1距离关系,即gamma(n + 1) = n!对于整数n。
本杰克逊

9

我们都从大学知道,计算乘法的最有效方法是使用对数。毕竟,人们为什么还要使用对数表数百年?

因此,根据身份,a*b=e^(log(a)+log(b))我们形成以下Python代码:

from math import log,exp

def fac_you(x):
    return round(exp(sum(map(log,range(1,x+1)))))

for i in range(1,99):
    print i,":",fac_you(i)

它会创建一个从1到的数字列表x,(+1是必需的,因为Python很烂),计算每个的对数,将这些数字求和,将e增大为和的幂,最后将值四舍五入到最接近的整数(因为Python很烂) 。Python具有一个用于计算阶乘的内置函数,但是它仅适用于整数,因此它不能产生大数(因为Python很烂)。这就是为什么需要以上功能的原因。

顺便说一句,给学生的一个一般提示是,如果某些事情没有按预期运行,那可能是因为该语言很烂。


希望我能在那儿再作一些说明,但是Python很烂
Mark K Cowan 2014年

1
我笑了“你FAC”
Number9

8

不幸的是,Javascript缺乏计算阶乘的内置方法。但是,您仍然可以在组合语言中使用其含义来确定该值:

数字n的阶乘是该大小的列表的排列数。

因此,我们可以生成n位数字的每个列表,检查它是否是一个排列,如果是,则增加一个计数器:

window.factorial = function($nb_number) {
  $nb_trials = 1
  for($i = 0; $i < $nb_number; $i++) $nb_trials *= $nb_number
  $nb_successes = 0
  __trying__:
  for($nb_trial = 0; $nb_trial < $nb_trials; $nb_trial++){
    $a_trial_split = new Array
    $nb_tmp = $nb_trial
    for ($nb_digit = 0; $nb_digit < $nb_number; $nb_digit++){
      $a_trial_split[$nb_digit] = $nb_tmp - $nb_number * Math.floor($nb_tmp / $nb_number)
      $nb_tmp = Math.floor($nb_tmp / $nb_number)
    }
    for($i = 0; $i < $nb_number; $i++)
      for($j = 0; $j < $nb_number; $j++)
        if($i != $j)
          if($a_trial_split[$i] == $a_trial_split[$j])
            continue __trying__
    $nb_successes += 1
  }
  return $nb_successes
}

alert("input a number")
document.open()
document.write("<input type = text onblur = alert(factorial(parseInt(this.value))))>")
document.close()


巨魔:

  • 输入匈牙利符号,snake_case 不必要的信号。那有多邪恶?
  • 发明了我自己的跳转标签约定,与该约定的当前用法不兼容。
  • 每个可能的变量都是偶然的全局变量。
  • 解决的办法不是O(n),不是O(n!),而是O(n^n)。仅此一项就足以在这里有资格。
  • 递增一个数字然后转换为base-n是生成序列列表的一种不好的方法。即使我们确实想要重复。神秘突破n> 13并不是唯一的原因。
  • 当然我们可以使用number.toString(base),但是不适用于36以上的基数。是的,我知道36!是很多,但仍...
  • 我是否提到Javascript具有模运算符?还是Math.pow?没有?那好吧。
  • 拒绝++在for循环之外使用使它更加神秘。而且,==是不好的。
  • 深层嵌套的无括号循环结构。同样,嵌套条件语句代替AND。同样,可以通过在处结束内部循环来避免外部条件$i
  • 的功能new Arraydocument.write(与朋友)和alert(而不是一个提示或输入标记)形成的功能选择罪一个完整的三连胜。为什么毕竟要动态添加输入?
  • 内联事件处理程序。哦,深度管道调试很困难。
  • 未引用的属性很有趣,并且周围的空格=使它们更难阅读。
  • 我是否已经提到我讨厌分号?

8

Ruby和WolframAlpha

该解决方案使用WolframAlpha REST API计算阶乘,RestClient提取解决方案,Nokogiri解析它。它不会重制任何轮子,而是使用经过良好测试和流行的技术以最现代的方式获得结果。

require 'rest-client'
require 'nokogiri'

n = gets.chomp.to_i
response = Nokogiri::XML(RestClient.get("http://api.wolframalpha.com/v2/query?input=#{n}!&format=moutput&appid=YOUR_APP_KEY"))
puts response.xpath("//*/moutput/text()").text

7

Java脚本

Javascript是一种功能编程语言,这意味着您必须对所有功能都使用函数,因为它的速度更快。

function fac(n){
    var r = 1,
        a = Array.apply(null, Array(n)).map(Number.call, Number).map(function(n){r = r * (n + 1);});
    return r;
}

1
你可以解释吗?
Mhmd 2013年

7
1不是功能。因此,您的代码很慢。
皮埃尔·阿劳德

4
@ArlaudPierre r = -~(function(){})一定会解决这个问题。
nitro2k01 2014年

4
我在工作机器上,所以我真的不想安装这种语言。在哪里可以找到将在浏览器中运行的版本?
joeytwiddle 2014年

3
我有点害怕使用Google,因为我的老板在他们那里有一个帐户,而且我不想他知道我在打高尔夫球。我一直在寻找可以运行Javascript的Firefox扩展,但似乎找不到。我的一些朋友在jsfiddle.net上运行Javascript,但这消耗了别人的电,有点像偷电。我妈妈说我不应该和这样的人闲逛,但是他们是我的朋友,我该怎么办?无论如何,她有时会吃比所需更多的奶精。感谢您的提示,我在Firefox中使用Ctrl-Shift-J或K。免责声明:#comment-
trolling

5

在Java中使用Bogo-Sort

public class Factorial {
    public static void main(String[] args) {
        //take the factorial of the integers from 0 to 7:
        for(int i = 0; i < 8; i++) {
            System.out.println(i + ": " + accurate_factorial(i));
        }
    }

    //takes the average over many tries
    public static long accurate_factorial(int n) {
        double sum = 0;
        for(int i = 0; i < 10000; i++) {
            sum += factorial(n);
        }
        return Math.round(sum / 10000);
    }

    public static long factorial(int n) {
        //n! = number of ways to sort n
        //bogo-sort has O(n!) time, a good approximation for n!
        //for best results, average over several passes

        //create the list {1, 2, ..., n}
        int[] list = new int[n];
        for(int i = 0; i < n; i++)
            list[i] = i;

        //mess up list once before we begin
        randomize(list);

        long guesses = 1;

        while(!isSorted(list)) {
            randomize(list);
            guesses++;
        }

        return guesses;
    }

    public static void randomize(int[] list) {
        for(int i = 0; i < list.length; i++) {
            int j = (int) (Math.random() * list.length);

            //super-efficient way of swapping 2 elements without temp variables
            if(i != j) {
                list[i] ^= list[j];
                list[j] ^= list[i];
                list[i] ^= list[j];
            }
        }
    }

    public static boolean isSorted(int[] list) {
        for(int i = 1; i < list.length; i++) {
            if(list[i - 1] > list[i])
                return false;
        }
        return true;
    }
}

实际上,这非常缓慢,并且对于更高的数字并不准确。


4

佩尔

阶乘可能是一个难题。像Google一样,类似map / reduce的技术可以通过分叉一系列过程并收集结果来拆分数学。在寒冷的冬天晚上,这将充分利用系统中的所有这些核心或CPU。

另存为f.perl和chmod 755以确保可以运行它。您确实安装了病理折衷的垃圾清单,不是吗?

#!/usr/bin/perl -w                                                              
use strict;
use bigint;
die "usage: f.perl N (outputs N!)" unless ($ARGV[0] > 1);
print STDOUT &main::rangeProduct(1,$ARGV[0])."\n";
sub main::rangeProduct {
    my($l, $h) = @_;
    return $l    if ($l==$h);
    return $l*$h if ($l==($h-1));
    # arghhh - multiplying more than 2 numbers at a time is too much work       
    # find the midpoint and split the work up :-)                               
    my $m = int(($h+$l)/2);
    my $pid = open(my $KID, "-|");
      if ($pid){ # parent                                                       
        my $X = &main::rangeProduct($l,$m);
        my $Y = <$KID>;
        chomp($Y);
        close($KID);
        die "kid failed" unless defined $Y;
        return $X*$Y;
      } else {
        # kid                                                                   
        print STDOUT &main::rangeProduct($m+1,$h)."\n";
        exit(0);
    }
}

巨魔:

  • 分叉O(log2(N))进程
  • 不检查您有多少个CPU或核心
  • 隐藏在每个过程中发生的许多bigint /文本转换
  • for循环通常比此代码快

ARGV[0]直到perl中的TIL 实际上是第一个参数,而不是脚本!
ThinkChaos 2014年

@plg我相信$ 0可能包含脚本文件名,但这与$ ARGV [0]不同
Paul

是的,这就是我读到的。我只是觉得奇怪,在Perl这不是$ARGV[0]因为大多数语言我知道一点有它存在
ThinkChaos

4

蟒蛇

只需O(n!* n ^ 2)算法即可找到阶乘。处理基本情况。没有溢出。

def divide(n,i):
    res=0
    while n>=i:
         res+=1
         n=n-i
    return res

def isdivisible(n,numbers):
    for i in numbers:
         if n%i!=0:
             return 0
         n=divide(n,i)
    return 1

def factorial(n):
    res = 1
    if n==0: return 1 #Handling the base case
    while not isdivisible(res,range(1,n+1)):
         res+=1
    return res

3

Well, there is an easy solution in Golfscript. You could use a Golfscript interpreter and run this code:

.!+,1\{)}%{*}/

Easy huh :) Good luck!


2
I don't know GolfScript, but this one disappoints me... Based on the other GolfScript examples on this site, I would have expected the answer to be !
Mr Lister

1
That is the negation operator. 0 becomes 1 and everything else becomes 0.
Martijn Courteaux

3

Mathematica

factorial[n_] := Length[Permutations[Table[k, {k, 1, n}]]]

It doesn't seem work for numbers larger than 11, and factorial[11] froze up my computer.


3

Ruby

f=->(n) { return 1 if n.zero?; t=0; t+=1 until t/n == f[n-1]; t }

The slowest one-liner I can imagine. It takes 2 minutes on an i7 processor to calculate 6!.


2

The correct approach for these difficult math problems is a DSL. So I'll model this in terms of a simple language

data DSL b a = Var x (b -> a)
             | Mult DSL DSL (b -> a)
             | Plus DSL DSL (b -> a)
             | Const Integer (b -> a) 

To write our DSL nicely, it's helpful to view it as a free monad generated by the algebraic functor

F X = X + F (DSL b (F X)) -- Informally define + to be the disjoint sum of two sets

We could write this in Haskell as

Free b a = Pure a
         | Free (DSL b (Free b a))

I will leave it to the reader to derive the trivial implementation of

join   :: Free b (Free b a) -> Free b a
return :: a -> Free b a
liftF  :: DSL b a -> Free b a

Now we can descibe an operation to model a factorial in this DSL

factorial :: Integer -> Free Integer Integer
factorial 0 = liftF $ Const 1 id
factorial n = do
  fact' <- factorial (n - 1)
  liftF $ Mult fact' n id

Now that we've modeled this, we just need to provide an actual interpretation function for our free monad.

denote :: Free Integer Integer -> Integer
denote (Pure a) = a
denote (Free (Const 0 rest)) = denote $ rest 0
...

And I'll leave the rest of the denotation to the reader.

To improve readability, it's sometimes helpful to present a concrete AST of the form

data AST = ConstE Integer
         | PlusE AST AST
         | MultE AST AST

然后是微不足道的反思

reify :: Free b Integer -> AST

然后递归评估AST很简单。


2

蟒蛇

以下是该解决方案的Python版本,该版本不限于Python中整数的32位(或在最近的系统上为64位)限制。为了解决这个限制,我们将使用字符串作为factorial例程的输入和输出,并在内部将字符串拆分为数字以执行乘法。

So here is the code: the getDigits function splits a string representing a number in to its digits, so "1234" becomes [ 4, 3, 2, 1 ] (the reverse order just makes the increase and multiply functions simpler). The increase function takes such a list and increases it by one. As the name suggests, the multiply function multiplies, e.g. multiply([2, 1], [3]) returns [ 6, 3 ] because 12 times 3 is 36. This works in the same way as you would multiply something with pen and paper.

Then finally, the factorial function uses these helper functions to calculate the actual factorial, for example factorial("9") gives "362880" as its output.

import copy

def getDigits(n):
    digits = []
    for c in n:
        digits.append(ord(c) - ord('0'))

    digits.reverse()
    return digits

def increase(d):
    d[0] += 1
    i = 0
    while d[i] >= 10:
        if i == len(d)-1:
            d.append(0)

        d[i] -= 10
        d[i+1] += 1
        i += 1

def multiply(a, b):
    subs = [ ]
    s0 = [ ]
    for bi in b:

        s = copy.copy(s0)
        carry = 0
        for ai in a:
            m = ai * bi + carry
            s.append(m%10)
            carry = m//10

        if carry != 0:
            s.append(carry)

        subs.append(s)
        s0.append(0)

    done = False
    res = [ ]
    termsum = 0
    pos = 0
    while not done:
        found = False
        for s in subs:
            if pos < len(s):
                found = True
                termsum += s[pos]

        if not found:
            if termsum != 0:
                res.append(termsum%10)
                termsum = termsum//10
            done = True
        else:
            res.append(termsum%10)
            termsum = termsum//10
            pos += 1

    while termsum != 0:
        res.append(termsum%10)
        termsum = termsum//10

    return res

def factorial(x):
    if x.strip() == "0" or x.strip() == "1":
        return "1"

    factorial = [ 1 ]
    done = False
    number = [ 1 ]
    stopNumber = getDigits(x)
    while not done:
        if number == stopNumber:
            done = True

        factorial = multiply(factorial, number)
        increase(number)

    factorial.reverse()

    result = ""
    for c in factorial:
        result += chr(c + ord('0'))

    return result

print factorial("9")

Notes

In python an integer doesn't have a limit, so if you'd like to do this manually you can just do

fac = 1
for i in range(2,n+1): 
    fac *= i

There's also the very convenient math.factorial(n) function.

This solution is obviously far more complex than it needs to be, but it does work and in fact it illustrates how you can calculate the factorial in case you are limited by 32 or 64 bits. So while nobody will believe this is the solution you've come up with for this simple (at least in Python) problem, you can actually learn something.


There is no limit on integer numbers in Python... right? You might need to explain this better.
Riking

@Riking Yes, in python there's no limit for integers. I've added a few notes to make it more clear.
brm

2

Python

The most reasonable solution is clearly to check through all numbers until you find the one which is the factorial of the given number.

print('Enter the number')
n=int(input())
x=1
while True:
    x+=1
    tempx=int(str(x))
    d=True
    for i in range(1, n+1):
        if tempx/i!=round(tempx/i):
            d=False
        else:
            tempx/=i
    if d:
        print(x)
        break

2

A most elegant recursive solution in C

Every one knows the most elegant solutions to factorials are recursive.

Factorial:

0! = 1
1! = 1
n! = n * (n - 1)!

But multiplication can also be defined recursively as successive additions.

Multiplication:

n * 0 = 0
n * 1 = n
n * m = n + n * (m - 1)

And so can addition as successive incrementations.

加成:

n + 0 = n
n + 1 = (n + 1)
n + m = (n + 1) + (m - 1)

C,我们可以使用++x--x处理原语(x + 1)(x - 1)分别,所以我们的一切定义。

#include <stdlib.h>
#include <stdio.h>

// For more elegance, use T for the type
typedef unsigned long T;

// For even more elegance, functions are small enough to fit on one line

// Addition
T A(T n, T m) { return (m > 0)? A(++n, --m) : n; }

// Multiplication
T M(T n, T m) { return (m > 1)? A(n, M(n, --m)): (m? n: 0); }

// Factorial
T F(T n) { T m = n; return (m > 1)? M(n, F(--m)): 1; }

int main(int argc, char **argv)
{
    if (argc != 2)
        return 1;

    printf("%lu\n", F(atol(argv[1])));

    return 0;
}

让我们尝试一下:

$ ./factorial 0
1
$ ./factorial 1
1
$ ./factorial 2
2
$ ./factorial 3
6
$ ./factorial 4
24
$ ./factorial 5
120
$ ./factorial 6
720
$ ./factorial 7
5040
$ ./factorial 8
40320

完美,虽然8!由于某种原因花了很长时间。哦,最优雅的解决方案并不总是最快的。让我们继续:

$ ./factorial 9

嗯,等它回来时,我会告诉你...


2

蟒蛇

正如@Matt_Sieker的回答所指出的那样,可以将阶乘分解为另外的部分-为什么,分解任务是编程的本质。但是,我们可以将其分解为1!

def complicatedfactorial(n):
    def addby1(num):
        return num + 1
    def addnumbers(a,b):
        copy = b
        cp2 = a
        while b != 0:
            cp2 = addby1(cp2)
            b -= 1
    def multiply(a,b):
        copy = b
        cp2 = a
        while b != 0:
            cp2 = addnumbers(cp2,cp2)
    if n == 0:
        return 1
    else:
        return multiply(complicatedfactorial(n-1),n)

我认为这段代码可以保证出现SO错误,因为

  1. 递归-预热

  2. 每层都会产生调用以进行乘法

  3. 生成对addnumbers的调用

  4. 生成对addby1的调用!

功能太多了吧?



1

TI基本84

:yumtcInputdrtb@gmail And:cReturnbunchojunk@Yahoo A!op:sEnd:theemailaddressIS Crazy ANSWER LOL

真的行 :)


1

Java脚本

显然,程序员的工作是做尽可能少的工作,并使用尽可能多的库。因此,我们要进口的jQuery math.js。现在,任务很简单,如下所示:

$.alert=function(message){
    alert(message);
}$.factorial=function(number){
    alert(math.eval(number+"!"));
    return math.eval(number+"!");
}
$.factorial(10);

1

Python

With just a slight modification of the standard recursive factorial implementation, it becomes intolerably slow for n > 10.

def factorial(n):
    if n in (0, 1):
        return 1
    else:
        result = 0
        for i in range(n):
            result += factorial(n - 1)
        return result

1

Bash

#! /bin/bash

function fact {
    if [[ ${1} -le 1 ]]; then
        return 1
    fi;

    fact $((${1} - 1))
    START=$(date +%s)
    for i in $(seq 1 $?); do sleep ${1}; done
    END=$(date +%s)
    RESULT=$(($END - $START))
    return $RESULT
}

fact ${1}
echo $?

1

Let's try to do it by the Monte Carlo Method. We all know that the probability of two random n-permutations being equal is exactly 1/n!. Therefore we can just check how many tests are needed (let's call this number b) until we get c hits. Then, n! ~ b/c.

Sage, should work in Python, too

def RandomPermutation(n) :           
    t = range(0,n)                   
    for i in xrange(n-1,0,-1):       
        x = t[i]                     
        r = randint(0,i)             
        t[i] = t[r]                  
        t[r] = x                     
    return t                         

def MonteCarloFactorial(n,c) :   
    a = 0                            
    b = 0                            
    t = RandomPermutation(n)         
    while a < c :                
        t2 = list(t)                 
        t = RandomPermutation(n)     
        if t == t2 :                 
            a += 1                   
        b += 1                       
    return round(b/c)            

MonteCarloFactorial(5,1000)
# returns an estimate of 5!

1

bash

Factorials are easily determined with well known command line tools from bash.

read -p "Enter number: " $n
seq 1 $n | xargs echo | tr ' ' '*' | bc

As @Aaron Davies mentioned in the comments, this looks much tidier and we all want a nice and tidy program, don't we?

read -p "Enter number: " $n
seq 1 $n | paste -sd\* | bc

1
i recommend the highly-underrated paste command: seq 1 $n | paste -sd\* | bc
Aaron Davies

2
@AaronDavies paste does look like a regular English word and with that easy to remember. Do we really want that? ;o)
jippie
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.