2015-09-23 13 views
12
#include <stdlib.h> 
#include <stdio.h> 

struct node; 
typedef struct node* PtrToNode; 

struct node { 
    long long n; 
    PtrToNode next; 
}; 

PtrToNode factorial(int n, PtrToNode init); 
void multiply(long long n, PtrToNode init, long long carry); 

int main() { 
    int n; 
    while (1) { 
    scanf("%d", &n); 
    if (n > 0) { 
     break; 
    } else if (n == 0){ 
     printf("1\n"); 
     return 0; 
    } else { 
     printf("Retry.\n"); 
    } 
    } 
    PtrToNode init = malloc(sizeof(struct node)); 
    init->n = 1; 
    init->next = NULL; 
    PtrToNode head = factorial(n, init); 
    PtrToNode tail = reverse(head); 
    PtrToNode backup = tail; 
    printf("%lld", tail->n); 
    tail = tail->next; 
    while(tail != NULL) { 
    printf("%04lld", tail->n); 
    tail = tail->next; 
    } 
    PtrToNode t; 
    while (backup != NULL) { 
    t = backup; 
    backup = backup->next; 
    free(t); 
    } 
} 


PtrToNode factorial(int n, PtrToNode init) { 
    for (int i = 1; i <= n; i++) 
    multiply(i, init, 0); 
    return init; 
} 

void multiply(long long n, PtrToNode init, long long carry) { 
    long long temp = n * init->n + carry; 
    init->n = temp % 10000; 
    carry = temp/10000; 
    if (init->next != NULL) { 
    multiply(n, init->next, carry); 
    } else if (carry > 0) { 
    init->next = malloc(sizeof(struct node)); 
    init->next->n = carry; 
    init->next->next = NULL; 
    } else { 
    return; 
    } 
} 

Questa è la mia funzione per calcolare 10000 fattoriale e ho calcolato la risposta corretta rispetto ai dati online. Ma, quando limito l'intervallo di n a [0.999], non riesco nemmeno a calcolare il fattoriale del 2000. Perché quando trasformo l'intervallo n per [0, 9999], allora può calcolare 2000! anche 10000 !?fattoriale 10000 in C

+0

La tua domanda ha quasi senso, ma non del tutto. "limit the n to [0.999]" e "transform the n to [0,9999]" sono confusi. – Teepeemm

+2

1) Non eseguire il cast di 'malloc' in C. 2) Non scrivere' type * ptr', ma 'type * ptr'. Questa non è una differenza per il compilatore, ma associa visivamente '*' al tipo, non al nome dato che è un compilatore fo re (prova 'int * ip, i':' i' non è un puntatore come 'int *' imetti al lettore). 3) Non digita 'typedef' un puntatore! Ciò nasconde la semantica e rende il tuo codice più complicato da leggere/capire. Solo i tipi normali 'typedef' e usano i puntatori in modo esplicito. 4) dovresti usare tipi non firmati. Hanno un comportamento di overflow ben definito. – Olaf

+0

Cosa succede quando il programma che limita 'n' a' [0,999] 'prova a calcolare' 2000! '? fa crash o dà una risposta sbagliata? In che modo la risposta è sbagliata? Magari postare un programma completo (incluso qualsiasi cosa chiamato 'factorial()') che mostri il problema. –

risposta

10

Il problema con la limitazione del cluster di cifre a tre cifre è che la moltiplicazione di un numero a tre cifre di un valore superiore a 1.000 può produrre un carry in cifra numero quattro.

Sebbene questo non crei un problema immediato, l'errore si accumula man mano che si porta il valore nella catena di calcolo. Con oltre 5.000 cifre nel risultato del 2000! l'overflow del carry produrrebbe certamente un errore visibile nel risultato. Questo succede intorno al 1258 ° passo del calcolo del 2000 !.

Questo non accade con i cluster a quattro cifre e 10.000 perché l'unico posto in cui il carry potrebbe "riversarsi" nella cifra successiva è il calcolo dell'ultimo cluster, e long long ha molto spazio per ospitare questo senza un troppo pieno.

+0

La domanda dell'OP indica che il calcolo di '10000!' Usando cluster a 4 cifre nel nodo funziona, ma che il codice non funziona quando si usano cluster a 3 cifre nel nodo per persino '2000!', Che ha qualcosa di meno di 6000 cifre. –

+0

@ Michael Burr Ah, ho letto il thread dei commenti ora, e vedo di cosa sta parlando. Modificherà. – dasblinkenlight