Pergunta

Assim, procedimento simples, calcular um número fatorial. Código é a seguinte.

int calcFactorial(int num)
{
    int total = 1;

    if (num == 0)
    {
        return 0;
    }

    for (num; num > 0; num--)
    {
        total *= num;
    }

    return total;
}

Agora, este fino e elegante funciona (Há certamente soluções mais rápidas e mais elegante, mas isso funciona para mim) para a maioria dos números. No entanto quando da entrada de números maiores, tais como 250 que, dito de outra maneira, craps fora. Agora, o primeiro par fatoriais "bits" para 250 são {250, 62250, 15126750, 15438000, 3813186000} para referência.

Meu código cospe {250, 62250, 15126750, 15438000, -481781296 } que é obviamente fora. Minha primeira suspeita foi, talvez, que eu tinha violado o limite de um inteiro de 32 bits, mas dado que 2 ^ 32 é 4294967296 Eu não penso assim. A única coisa que eu posso pensar é, talvez, que rompe um limite assinado 32-bit, mas não deveria ser capaz de pensar sobre esse tipo de coisa? Se a ser assinado é o problema que posso resolver isto fazendo o inteiro sem sinal, mas isso seria apenas uma solução temporária, como as próximas rendimentos iteração 938043756000 que é muito acima do limite de 4294967296.

Assim, é meu problema o limite assinado? Se assim for, o que posso fazer para calcular grandes números (embora eu tenha um "LargeInteger" class eu fiz há um tempo atrás que pode ser adequado!) Sem entrar em toda este problema novamente?

Foi útil?

Solução

2 ^ 32 não lhe dá o limite para inteiros assinados.

O limite inteiro assinado é realmente 2147483647 (se você está desenvolvendo no Windows usando as ferramentas de MS, outros toolsuites / plataformas teriam seus próprios limites que são provavelmente similares).

Você vai precisar de uma grande biblioteca número C ++ como este .

Outras dicas

Além dos outros comentários, eu gostaria de destacar dois erros graves em seu código.

  • Você não tem nenhuma proteção contra números negativos.
  • O fatorial de zero é um, não zero.

Sim, você atingiu o limite. Um int em C ++ é, por definição, assinado. E, uh, não, C ++ não pensa, nunca. Se você diga a ele para fazer uma coisa, ele vai fazê-lo, mesmo que seja obviamente errado.

Considere o uso de uma grande biblioteca número. Há muitos deles em torno de C ++.

Se você não especifica sinal ou sem sinal, o padrão é assinado. Você pode modificar isso usando uma opção de linha de comando do seu compilador.

Basta lembrar, C (ou C ++) é uma linguagem de nível muito baixo e não precisamente o que você diga a ele para fazer . Se você diga a ele para armazenar esse valor em um int assinado, que é o que ele vai fazer. Você como o programador tem que descobrir quando isso é um problema. Não é a função da linguagem.

calculadora My Windows ( Start-Run-Calc ) me que

diz
hex (3813186000) =         E34899D0
hex (-481781296) = FFFFFFFFE34899D0

Então, sim, a causa é o limite assinado. Desde fatoriais pode, por definição, só será positivo, e só pode ser calculado para números positivos, tanto o argumento e o valor de retorno deve ser números não assinados de qualquer maneira. (Eu sei que todo mundo usa int i = 0 em loops, por isso, I. Mas que deixou de lado, devemos usar variáveis ??sempre não assinados se o valor não pode ser negativo, é uma boa prática IMO).

O problema geral com fatoriais é que eles podem facilmente gerar muito grandes números. Você poderia usar um float, sacrificando assim a precisão, mas evitando o problema de estouro de inteiro.

Oh esperar, de acordo com o que eu escrevi acima, você deve fazer que um flutuador sem assinatura; -)

Você tem um problema de estouro. Fatoriais pode facilmente exceder os limites de inteiros. Você poderia mudar de função para retornar duplas, mas que só vai comprar-lhe um pouco de espaço mais. Em aplicações, muitas vezes você precisa fatoriais multiplicam vezes números muito pequenos, onde o resultado final vai caber dentro de um casal, mas os passos intermediários não vai. Aqui está um artigo que explica como lidar com esta situação: http://www.johndcook.com/blog/2008/04/24/how-to-calculate-binomial-probabilities/

Se eu me lembro bem:

unsigned short int = max 65535

unsigned int = max 4294967295

unsigned long = max 4294967295

unsigned long long (Int64) = max 18446744073709551615

fonte Editado:

Int / valores Longo Max

Modern Compiler Variável

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top