2015-09-23 73 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; 
    } 
} 

這是我的函數來計算10000階乘,我已經計算出了與在線數據相比的正確答案。但是,當我將n的範圍限制爲[0.999]時,我甚至無法計算2000階乘。爲什麼當我將n'範圍轉換爲[0,9999]時,它可以計算2000!甚至10000!10000因子C

+0

你的問題幾乎有道理,但不完全。 「將n限制爲[0.999]」和「將n轉換爲[0,9999]」令人困惑。 – Teepeemm

+2

1)不要在C中投入'malloc'的結果。2)不要寫'type * ptr',而要寫'type * ptr'。這對編譯器來說沒有什麼區別,但它可視化地將'*'綁定到類型,而不是名稱,因爲它是對編譯器的(嘗試'int * ip,i':'i'不是'int *符合讀者)。 3)不要「輸入」一個指針!這隱藏了語義,並使您的代碼更易於閱讀/理解。只有'typedef'正常類型並明確使用指針。 4)你應該使用無符號類型。他們有一個明確的溢出行爲。 – Olaf

+0

當限制'n'到'[0,999]'的程序試圖計算'2000!'時會發生什麼?它會崩潰還是給出錯誤的答案?答案錯誤的方式是什麼?也許發佈一個完整的(包括任何調用'factorial()')程序來顯示問題。 –

回答

10

將您的數字簇限制爲三位數的問題是,將三位數乘以1,000以上的值可能會將數字乘以四位數。

儘管這不會產生即時問題,但是隨着您將計算鏈上的值擡起,錯誤將會累積。 2000年的結果超過5000個數字!進位溢出肯定會在結果中產生一個可見的錯誤。這發生在計算2000年的第1258步!

這不會發生在四位數簇和10,000之間,因爲進位可能「溢出」到下一位的唯一地方是計算最後一個簇,並且long long有足夠的空間來容納這個,而沒有溢出。

+0

OP的問題表明,在節點中使用4位簇計算'10000!'是有效的,但是在節點中使用3位數簇的情況下甚至連'2000!'都少於6000位的情況下,代碼不起作用。 –

+0

@MichaelBurr啊,我現在閱讀了評論的主題,我看到他在說什麼。將編輯。 – dasblinkenlight