Como encontro o fatorial de um número positivo?

18

O desafio:

Escreva um programa ou uma função que insira um número positivo e retorne seu fatorial .

Nota: Esta é uma pergunta de . Por favor, não leve a sério a pergunta e / ou respostas. Mais informações aqui . Toda pergunta de também é uma questão de , de modo que a resposta mais votada vence.

alefalpha
fonte
6
Veja também o programador The Evolution of Haskell .
Petr Pudlák
4
-1, desculpe, porque estamos recebendo uma enorme quantidade dessas perguntas de trollagem de código e isso realmente não adiciona nada de novo a elas
Doorknob
A trollagem de código está sendo removida, conforme a posição oficial. Esta pergunta tem uma quantidade razoável de votos com muitas respostas, muitas das quais são extremamente votadas. Ele recebeu pouco mais de 50% de "excluídos" dos votos na enquete , mas é o único que recebeu tantas respostas e votos, por isso estou bloqueando-o por um significado histórico.
Maçaneta

Respostas:

46

Este é um problema de computação numérica muito simples que podemos resolver com a aproximação de Stirling :

Fórmula de aproximação de Stirling

Como você pode ver, essa fórmula possui uma raiz quadrada, da qual também precisaremos uma maneira de aproximar. Vamos escolher o chamado "método babilônico" para isso, porque é sem dúvida o mais simples:

Método babilônico

Observe que calcular a raiz quadrada dessa maneira é um bom exemplo de recursão.

Reunir tudo isso em um programa Python nos dá a seguinte solução para o seu problema:

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)

Com uma modificação simples, o programa acima pode gerar uma tabela clara de fatoriais:

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

Este método deve ser suficientemente preciso para a maioria dos aplicativos.

nwk
fonte
16
A simplicidade e precisão deste método o tornam um vencedor claro #
Joe the Person
44

C #

Desculpe, mas eu odeio função recursiva.

public string Factorial(uint n) {
    return n + "!";
}
tia
fonte
1
Tecnicamente, você satisfez o breve! ;) +1 por abuso breve
WallyWest
36

Java

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();
}
}
emory
fonte
16
Eu tentei - muito eficiente. Será enviado com o próximo lançamento. :)
Johannes
Além da "síndrom dos números mágicos", essa poderia ser uma boa implementação, contanto que n <13, muito menos pilhas. Escreva "case 4: return 4 * 3 * 2;" e você teria uma classe decente, muito mais rápida que a antiga recursiva.
Fabinout
6
@Fabinout, a implementação está correta mesmo para n> = 13. 13!> Inteiro.MAX_VALUE.
Emory
21

Pitão

Obviamente, a melhor maneira de resolver qualquer problema é usar expressões regulares:

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)
Petr Pudlák
fonte
1
É claro que, na verdade :)
Pierre Arlaud
15

Haskell

Código curto é um código eficiente, então tente isso.

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

Por que está trollando:

Eu riria de qualquer codificador que escrevesse isso ... A ineficiência é linda. Provavelmente também incompreensível para qualquer programador Haskell que realmente não possa escrever uma função fatorial.

Edit: Eu postei isso há um tempo atrás agora, mas pensei em esclarecer para futuras pessoas e pessoas que não sabem ler Haskell.

O código aqui pega a lista dos números de 1 a n, cria a lista de todas as permutações dessa lista e retorna o comprimento dessa lista. Na minha máquina, leva cerca de 20 minutos para 13 !. E então deve levar quatro horas para 14! e depois dois dias e meio por 15 !. Exceto que, em algum momento, você ficará sem memória.

Edit 2: Na verdade, você provavelmente não ficará sem memória devido a isso ser Haskell (veja o comentário abaixo). Você pode forçá-lo a avaliar a lista e mantê-la na memória de alguma forma, mas não sei o suficiente sobre como otimizar (e não otimizar) o Haskell para saber exatamente como fazer isso.

jgon
fonte
Hediondo e ao mesmo tempo tão elegante, tudo ao mesmo tempo.
PLL
1
Tem certeza do problema de memória? A qualquer momento, você precisa armazenar na memória: - a lista [1..n]. - Uma permutação específica de [1..n], consignada a um thunk pelo restante das permutações (polinômio de entrada n). - Um acumulador para a lengthfunção.
John Dvorak
Ponto justo, provavelmente não na verdade. Realmente não pensei muito nisso. Vou adicionar um comentário na parte inferior.
jgon
10

C #

Como esse é um problema de matemática, faz sentido usar um aplicativo projetado especificamente para resolver problemas de matemática para fazer esse cálculo ...

Passo 1:

Instale o MATLAB. Acho que um teste funcionará, mas esse problema super complicado é provavelmente importante o suficiente para merecer a compra da versão completa do aplicativo.

Passo 2:

Inclua o componente MATLAB COM no seu aplicativo.

Etapa 3:

public string Factorial(uint n) {
    MLApp.MLApp matlab = new MLApp.MLApp();
    return matlab.Execute(String.Format("factorial({0})", n);
}
Moshe Katz
fonte
O Matlab para estudantes começa em US $ 100. Versões profissionais ou licenças de sites podem chegar aos milhares.
Moshe Katz
4
Moshe Katz - justificado porque fatoriais.
Mike H.
9

C #

Os fatoriais são uma operação matemática de nível superior que pode ser difícil de digerir de uma só vez. A melhor solução em problemas de programação como esse é dividir uma tarefa grande em tarefas menores.

Agora n! é definido como 1 * 2 * ... * n, portanto, em essência, multiplicação repetida, e multiplicação nada mais é que adição repetida. Portanto, com isso em mente, o seguinte resolve esse problema:

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;
    }
}
Matt Sieker
fonte
Você tem um gargalo enviar tudo isso através de uma CPU ou núcleo, que eu acho que pode ter resolvido na minha resposta :-)
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;
}

Trolls:

  • Uma maneira 100% correta de calcular o fatorial que ignora completamente o objetivo de fazê-lo de forma iterativa ou recursiva.
  • Você não tem idéia do por que funciona e não pôde generalizá-lo para fazer qualquer outra coisa.
  • Mais caro do que apenas computá-lo com matemática inteira.
  • O código "subótimo" mais óbvio ( z = n - 1 + 1) é na verdade auto-documentado, se você souber o que está acontecendo.
  • Para trolling extra, devo calcular p[]usando um cálculo recursivo dos coeficientes da série!

(É a aproximação de Lanczos da função gama )

Ben Jackson
fonte
Existe algum ponto - 1 + 1aqui? Meu compilador o otimiza (não é um número de ponto flutuante, onde a otimização de códigos como esse pode ser perigosa), portanto parece desnecessário.
21978 Konrad Borowski
4
@xfix: double z = n - 1faz parte da aproximação da função gama. O + 1é do relacionamento que gamma(n + 1) = n!para o número inteiro n.
Ben Jackson
9

Todos sabemos da faculdade que a maneira mais eficiente de calcular uma multiplicação é através do uso de logaritmos. Afinal, por que mais as pessoas usariam as tabelas de logaritmos por centenas de anos?

Portanto, a partir da identidade a*b=e^(log(a)+log(b)), formamos o seguinte código 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)

Ele cria uma lista de números de 1até x(o +1necessário porque o Python é uma porcaria) calcula o logaritmo de cada um, soma os números, aumenta o e ao poder da soma e finalmente arredonda o valor para o número inteiro mais próximo (porque o Python é uma porcaria) . O Python possui uma função interna para calcular fatoriais, mas funciona apenas para números inteiros, portanto, não pode produzir grandes números (porque o Python é péssimo). É por isso que a função acima é necessária.

Aliás, uma dica geral para os alunos é que, se algo não funcionar como o esperado, é provavelmente porque o idioma é péssimo.

nitro2k01
fonte
Gostaria de poder dar alguns votos extras para a descrição, mas Python é uma porcaria #
Mark K Cowan
1
Eu ri de "fac you"
Número9
8

Infelizmente, o Javascript não possui uma maneira integrada de calcular o fatorial. Mas, você pode usar seu significado na combinatória para determinar o valor, no entanto:

O fatorial de um número n é o número de permutações de uma lista desse tamanho.

Assim, podemos gerar todas as listas de números de n dígitos, verificar se é uma permutação e, se sim, incrementar um contador:

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()


Trolls:

  • Digita notação húngara, snake_case e sigilos desnecessários . Quão mal é isso?
  • Inventei minha própria convenção para etiquetas de salto, incompatível com o uso atual desta convenção.
  • Toda variável possível é acidentalmente global.
  • A solução não é O(n), não O(n!), mas O(n^n). Isso por si só seria suficiente para se qualificar aqui.
  • Incrementar um número e depois converter como base-n é uma maneira ruim de gerar uma lista de sequências. Mesmo se nós quiséssemos duplicatas. Romper misteriosamente por n> 13 não é a única razão.
  • Claro que poderíamos ter usado number.toString(base), mas isso não funciona para bases acima de 36. Sim, eu sei 36! é muito , mas ainda assim ...
  • Eu mencionei que o Javascript tinha o operador de módulo? Ou Math.pow? Não? Ah bem.
  • Recusar-se a usar ++fora dos loops for torna ainda mais misterioso. Além disso, ==é ruim.
  • Construções de loop sem pulseira profundamente aninhadas. Além disso, condicionais aninhados em vez de AND. Além disso, a condição externa poderia ter sido evitada terminando o loop interno em $i.
  • As funções new Array, document.write(com amigos) e alert(em vez de um prompt ou um rótulo de entrada) formam um trio completa dos pecados função de escolha. Por que a entrada é adicionada dinamicamente, afinal?
  • Manipuladores de eventos em linha. Ah, e a tubulação profunda é um inferno para depurar.
  • Os atributos não citados são divertidos, e os espaços ao redor os =tornam ainda mais difíceis de ler.
  • Já mencionei que odeio ponto e vírgula?
John Dvorak
fonte
8

Ruby e WolframAlpha

Esta solução usa a API REST WolframAlpha para calcular o fatorial, com RestClient para buscar a solução e Nokogiri para analisá-la. Não reinventa nenhuma roda e usa tecnologias bem testadas e populares para obter o resultado da maneira mais moderna possível.

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
migimunz
fonte
7

Javascript

Javascript é uma linguagem de programação funcional, isso significa que você precisa usar funções para tudo, porque é mais rápido.

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;
}
Luka
fonte
1
Você pode explicar?
Mhmd
7
1 não é uma função. Seu código é, portanto, lento.
Pierre Arlaud
4
@ArlaudPierre r = -~(function(){})certamente resolverá isso.
Nitro2k01
4
Como estou em uma máquina de trabalho, não quero realmente instalar esse idioma. Onde posso encontrar uma versão que será executada no meu navegador?
precisa saber é o seguinte
3
Estou com um pouco de medo de usar o Google porque meu chefe tem uma conta com eles e não quero que ele saiba que estou jogando golfe no trabalho. Eu estava procurando por uma extensão para o Firefox que pudesse executar o Javascript, mas não consigo encontrar uma. Alguns de meus amigos usam Javascript no jsfiddle.net, mas estão usando a eletricidade de outra pessoa, que é um pouco como roubar. Minha mãe disse que eu não deveria ficar com pessoas assim, mas elas são minhas amigas, então o que posso fazer? De qualquer forma, ela às vezes toma mais creme do que precisa. Obrigado pelas dicas, eu uso Ctrl-Shift-J ou K no Firefox. Disclaimer: # comentário-trolling
joeytwiddle
5

Usando o Bogo-Sort em Java

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;
    }
}

Na verdade, isso funciona muito devagar e não é preciso para números mais altos.

James Hagborg
fonte
4

PERL

O fatorial pode ser um problema difícil. Uma técnica de mapear / reduzir como - assim como o Google usa - pode dividir a matemática iniciando vários processos e coletando os resultados. Isso fará bom uso de todos esses núcleos ou cpus em seu sistema em uma noite fria de inverno.

Salve como f.perl e chmod 755 para garantir que você possa executá-lo. Você tem o Lister de lixo patologicamente eclético instalado, não é?

#!/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);
    }
}

Trolls:

  • bifurca processos O (log2 (N))
  • não verifica quantas CPUs ou núcleos você possui
  • Oculta muitas conversões bigint / texto que ocorrem em todos os processos
  • Um loop for geralmente é mais rápido que esse código
Paulo
fonte
ATÉ que em perl ARGV[0]é realmente o primeiro argumento e não o script!
ThinkChaos
@plg Eu acredito que $ 0 pode conter o nome do arquivo do script, mas não é o mesmo que $ ARGV [0]
Paul
Sim, é isso que eu li. Eu só descobri que é surpreendente que não em perl que é $ARGV[0]porque a maioria das línguas que eu sei um pouco tê-lo lá
ThinkChaos
4

Pitão

Apenas um algoritmo O (n! * N ^ 2) para encontrar o fatorial. Caixa base manuseada. Sem estouros.

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
Sudharsan Mohan
fonte
3

Bem, existe uma solução fácil no Golfscript. Você pode usar um intérprete Golfscript e executar este código:

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

Fácil hein :) Boa sorte!

Martijn Courteaux
fonte
2
Eu não sei GolfScript, mas este decepciona-me ... Com base nos outros exemplos GolfScript neste site, eu teria esperado que a resposta seja!
Sr. Lister
1
Esse é o operador de negação. 0 torna-se 1 e tudo o mais se torna 0.
Martijn Courteaux
3

Mathematica

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

Não parece funcionar para números maiores que 11, e o fatorial [11] congelou meu computador.

Stephen Montgomery-Smith
fonte
3

Rubi

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

A frase mais lenta que posso imaginar. Demora 2 minutos em um processador i7 para calcular 6!.

reescrito
fonte
2

A abordagem correta para esses problemas matemáticos difíceis é uma DSL. Então, eu vou modelar isso em termos de uma linguagem simples

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

Para escrever bem o nosso DSL, é útil visualizá-lo como uma mônada livre gerada pelo functor algébrico

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

Poderíamos escrever isso em Haskell como

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

Deixarei ao leitor derivar a implementação trivial de

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

Agora podemos descrever uma operação para modelar um fatorial neste DSL

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

Agora que modelamos isso, precisamos fornecer uma função de interpretação real para nossa mônada livre.

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

E deixarei o resto da denotação para o leitor.

Para melhorar a legibilidade, às vezes é útil apresentar um AST concreto da forma

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

e depois corrigir uma reflexão trivial

reify :: Free b Integer -> AST

e é fácil avaliar recursivamente o AST.

Daniel Gratzer
fonte
2

Pitão

Abaixo está uma versão Python da solução, que não se limita ao limite de 32 bits (ou 64 bits em um sistema muito recente) para números inteiros no Python. Para contornar essa limitação, devemos usar uma string como entrada e saída para a factorialrotina e dividir internamente a string em seus dígitos para poder executar a multiplicação.

Então, aqui está o código: a getDigitsfunção divide uma string que representa um número em seus dígitos, de forma que "1234" se torna [ 4, 3, 2, 1 ](a ordem inversa apenas simplifica as funções increasee multiply). A increasefunção pega essa lista e aumenta em um. Como o nome sugere, a multiplyfunção se multiplica, por exemplo, multiply([2, 1], [3])retorna [ 6, 3 ]porque 12 vezes 3 é 36. Isso funciona da mesma maneira que você multiplicaria algo com caneta e papel.

Finalmente, a factorialfunção usa essas funções auxiliares para calcular o fatorial real, por exemplo, factorial("9")fornece "362880"como saída.

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")

Notas

No python, um número inteiro não tem um limite; portanto, se você quiser fazer isso manualmente, basta

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

Há também a math.factorial(n)função muito conveniente .

Essa solução é obviamente muito mais complexa do que precisa, mas funciona e, de fato, ilustra como você pode calcular o fatorial no caso de você estar limitado por 32 ou 64 bits. Portanto, embora ninguém acredite que esta é a solução que você encontrou para esse problema simples (pelo menos em Python), você pode realmente aprender alguma coisa.

brm
fonte
Não há limite para números inteiros em Python ... certo? Você pode precisar explicar isso melhor.
Riking
@ Vikings Sim, em python não há limite para números inteiros. Adicionei algumas notas para tornar mais claro.
Br
2

Pitão

A solução mais razoável é claramente verificar todos os números até encontrar o fatorial do número fornecido.

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
PygameNerd
fonte
2

A solução recursiva mais elegante em C

Todos sabem que as soluções mais elegantes para os fatoriais são recursivas.

Fatorial:

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

Mas a multiplicação também pode ser definida recursivamente como adições sucessivas.

Multiplicação:

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

E o mesmo pode acontecer com incrementos sucessivos.

Adição:

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

Em C, podemos usar ++xe --xmanipular as primitivas (x + 1)e (x - 1)respectivamente, para que tenhamos tudo definido.

#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;
}

Vamos tentar:

$ ./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

Perfeito, apesar de 8! demorou muito tempo por algum motivo. Bem, as soluções mais elegantes nem sempre são as mais rápidas. Vamos continuar:

$ ./factorial 9

Hmm, eu vou deixar você saber quando voltar ...


fonte
2

Pitão

Como a resposta de @ Matt_Sieker indicou, os fatoriais podem ser divididos em adição - por que, dividir tarefas é a essência da programação. Mas, podemos dividir isso em adição por 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)

Eu acho que esse código garante um erro SO, porque

  1. Recursão - aquece

  2. Cada camada gera chamadas para multiplicar

  3. que gera chamadas para addnumbers

  4. que gera chamadas para addby1!

Muitas funções, certo?

Dan the Man
fonte
1

TI-Basic 84

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

Realmente funciona :)

Timtech
fonte
1

Javascript

Obviamente, o trabalho de um programador é fazer o mínimo possível de trabalho e usar o maior número possível de bibliotecas. Portanto, queremos importar jQuery e math.js . Agora, a tarefa é simples assim:

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

Pitão

Com apenas uma ligeira modificação da implementação fatorial recursiva padrão, torna-se intoleravelmente lento para 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
dan04
fonte
1

Bater

#! /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 $?
alaroldai
fonte
1

Vamos tentar fazê-lo pelo método de Monte Carlo . Todos sabemos que a probabilidade de duas n- permutações aleatórias serem iguais é exatamente 1 / n! . Portanto, podemos apenas verificar quantos testes são necessários (vamos chamar esse número b ) até obtermos c hits. Então, n! ~ b / c .

Sage, também deve funcionar em Python

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!
yo '
fonte
1

bater

Os fatoriais são facilmente determinados com ferramentas de linha de comando conhecidas do bash.

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

Como @Aaron Davies mencionado nos comentários, isso parece muito mais organizado e todos nós queremos um programa agradável e organizado, não é?

read -p "Enter number: " $n
seq 1 $n | paste -sd\* | bc
jippie
fonte
1
eu recomendo o pastecomando altamente subestimado :seq 1 $n | paste -sd\* | bc
Aaron Davies
2
O @AaronDavies pasteparece uma palavra comum em inglês e fácil de lembrar. Nós realmente queremos isso? ; o)
jippie 14/01