簡體   English   中英

為什么代碼拋出分段錯誤?

[英]Why is the code throwing segmentation fault?

問題是找到存在最長collat​​z系列的數字i<=n, n<=500000。 數字 n 的 Collat​​z 系列終止於 1,條件是如果 n 是偶數,則下一項 = n/2 如果 n 是奇數,下一項 = 3*n + 1

事實上,對於所有數字,collat​​z 系列總是以 1 終止。

因此,任何數字都不會在其 collat​​z 系列中重復。 使用這個事實,我編寫了以下代碼邏輯:我開始一個 while 循環,直到 n 並且對於每次迭代,我存儲該 i 的系列長度。 如果 i 出現在一系列 n >= r > i 中,那么 i 終止循環並將 i 的長度添加到 r。 例如,假設 3 的系列是 3, 10, 5, 16, 8, 4, 2, 1。現在對應於 2 的長度已經存儲在 series_length 數組中,所以我使用該值。

然后旁邊的 for 循環,找到最長的系列並顯示答案。

該代碼在 n <= 1818 時工作正常,准確地說,但顯示分段錯誤(不知道為什么 :()。請幫忙

代碼 :

#include <stdio.h>

int length = 0, series_length[500000], maxlength = 0;

void store_length(int n) {
    while(n > 1 && series_length[n] == 0) {
        length++;
        if(n%2 == 0) {
            n = n/2;
        }
        else {
            n = 3*n + 1;
        }
    }
    length += series_length[n];
}

int main() {
    int n, i = 1, result;
    scanf("%d", &n);
    series_length[1] = 1;//redundant statement

    while(i <= n) {
        store_length(i);
        series_length[i] = length;
        length = 0;
        i++;
    }

    for(int i = 1;i <= n; i++) {
        if(maxlength <= series_length[i]) {
            maxlength = series_length[i];
            result = i;
        }
    }

    printf("%d %d\n", result, maxlength);

    return 0;
}

輸入- 10 輸出- 9 20(如預期)

輸入 - 100000 輸出 - 預計出現分段故障 - 77031 351

您的n值超出范圍。

你有一條線n = 3*n + 1; 在函數store_length

使用輸入為100000的 gdb 運行它給出

 Thread 1 received signal SIGSEGV, Segmentation fault.
 0x0000000000401545 in store_length (n=532060) at 29_01.c:6
6           while(n > 1 && series_length[n] == 0) {
(gdb) p n
$1 = 532060
  • 僅在合適時才存放
  • ...如果已經計算過就使用它
  • 避免全局變量
  • 更喜歡無符號值
  • [使用描述性變量名稱]

#include <stdio.h>

#define THE_SIZE 500000

unsigned series_length[THE_SIZE]= {0,};

unsigned get_length(unsigned val) {
    unsigned steps;
    for (steps=0; val > 1 ; steps++) {
        if (val < THE_SIZE && series_length[val]) { steps += series_length[val]; break; }
        if(val %2 ) val = 3*val + 1;
        else val /= 2;
    }
    return steps;
}

int main( int argc, char **argv) {
    unsigned top, val , result;
    unsigned  best,maxlength ;

    sscanf(argv[1], "%u", &top);

    series_length[1] = 1;//redundant statement

    best = maxlength = 0;
    for(val=1;val <= top; val++) {
        result = get_length(val);
        // store it if it fits;
        if(val<THE_SIZE) series_length[val] = result;
        if (result < maxlength) continue;
        best = val; maxlength = result;
    }


    printf("%u %u\n", best, maxlength);

    return 0;
}

最后,為了好玩,把數組變小

#define THE_SIZE 500

,對於給定的值,程序應該給出相同的結果。 (確實如此)

您得到最大值 24,648,077,896,n = 487039。

因此,您必須對n使用long long int類型,並且應該使用 24,648,077,896 個整數的數組以避免分段錯誤。 不幸的是,我從未成功分配過 100GB 的塊。 因此,您的優化不可行。

如果沒有陣列優化,我可以在 265 毫秒內掃描所有 500000 個 n 值。

這是我的代碼:

#include <stdio.h>

int collatz_length(int n) {
    int length = 0;
    long long int v = (long long int)n;
    while (v > 1) {
        if ((v&1) == 0)
            v = v / 2;
        else
            v = v*3 + 1;
        length++;
    }
    return length;
}

int main() {
    int max_i, max_l = 0;
    for (int i = 500000; i > 0; i--) {
        int l = collatz_length(i);
        if (l > max_l){
            max_l = l;
            max_i = i;
        }
    }
    printf("i: %d l: %d\n", max_i, max_l);
    return 0;
}

暫無
暫無

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

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