簡體   English   中英

為什么該程序給我SIGFPE?

[英]Why is this program giving me a SIGFPE?

我在下面的程序中收到SIGFPE錯誤,無法想到將其刪除的方法。

#include <stdio.h>

unsigned int fact(unsigned long int n)
{
    if (n <= 0)
        return 1;
    return n*fact(n-1);
}


int main(){
    int t,r,x,y,z,sum=0,n;

    scanf("%d",&t);

    for(int l=0; l<t; l++){

        scanf("%d",&n );

        if(n%2==0){
            for(int j=n,i=0,k=n; k>=0&&j>0;i++, j++,k-=2){
                x=fact(n-i);
                y=fact(k);
                z=fact(n-k-i);
                sum=sum+  (x)/(y*z);
            }
            printf("%d\n",sum );
        }

        if(n%2!=0){
            for(int j=n,i=0,k=n; k>=1&&j>0;i++, j++,k-=2){
                x=fact(n-i);
                y=fact(k);
                z=fact(n-k-i);
                sum=sum+  (x)/(y*z);

            }
            printf("%d\n",sum);
        }
        sum=0;

    }
    return 0;
}

我正在嘗試計算需要階乘的級數,但這給了我SIGFPE錯誤。 我使用35作為輸入。

鏈接到問題: 屏幕截圖

35! 遠遠超過了平台上unsigned int的容量。

會發生什么然后是fact(35)返回0,其結果在被零除因此SIGFPE(F loating p ointëxception)。

考慮使用unsigned long long類型,但這對35也不起作用,因為35! 真的很大

除了Jabberwocky的答案。

溢出不是唯一的原因,哦,有一個“整數”溢出...

fact(34)返回驚人的結果0。

如果是uint64返回值, uint64返回arg

unsigned long long fact(unsigned long long n)

然后用

printf("%llx",x);

您將得到結果:445da75b00000000

將其強制轉換為int即可得到完美的0。

這是合乎邏輯的,因為您已將許多偶數相乘,並且有些數字是2的偶數冪。

您只需要乘以32 2s即可達到以下結果:

  • 2,6,10,14,18,22,26,30,34每個給您一個2所以您有9 2s
  • 4,12,20,28分別給您4,即2 * 2,所以它給您8 2s,所以您已經有17 2s
  • 8,24給您8,即2 * 2 * 2,所以您還有6 2s,總共是23 2s
  • 16給你更多4 2s,所以你有27 2s
  • 32給您5 2s,所以您恰好有32 2s。

在您的程序中,您將為每個可能的兩個任務天數計算二項式系數C(n,k)。 公式很簡單:

C(n, k) = n! / (k! * (n - k)!)

但是直接使用此公式有幾個問題:中間結果,即階乘,迅速溢出。 無符號的32位整數最多可容納12!個事實,無符號的64位整數最多可容納20!個,但是此后,您將需要bignum庫。 問題陳述指出,任務數N最多為80。我相信選擇了此限制,以便您可以使用<stdint.h> uint64_t進行所有計算。

還有其他問題; 雷蒙·陳(Raymond Chen)盡我所能勾勒出它們的優美輪廓。 他還提出了一種計算二項式系數的簡單方法,您可以采用:

uint64_t binom(uint64_t n, uint64_t k)
{
    uint64_t c = 1u;
    uint64_t i;

    for (i = 0; i < k; i++) {
        c *= n - i;
        c /= i + 1;
    }

    return c;
}

哦,您不需要區分N的奇數和偶數。

挑戰有一個奇怪的地方:N是每個測試用例的唯一參數,范圍可以從1到80,但是最多可以有10,000個測試用例。 如果超過80個,N將重復。 也許他們希望您將結果記憶在一個數組中,以便第一次計算該結果時將其存儲起來,而下次您必須再次針對相同的N計算時,只需使用預先計算的值即可。 這樣可以節省時間,並且“超過時間限制”是在線競賽中非常常見的錯誤。

您也可以嘗試計算前幾個結果,例如N的范圍是1到10,並打印出來。 注意到模式嗎? 看,您根本不需要二項式系數。 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM