首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言求素數平方根和:邏輯錯誤分析與代碼規範重構

     編輯:程式設計綜合問答

原代碼問題分析

用戶代碼片段:

for(i=3; i<=n; i++) {
    k = sqrt(i);
    for(j=2; j<=k; j++) {
        if(i%j==0) break;
    }
    if(j >= k+1) {  // 關鍵判斷
        sum += sqrt(i);
    }
}

核心邏輯解析

1. 內層循環終止條件

  • `for(j=2; j<=k; j++)` 當 `j` 遞增到 `k+1` 時,條件 `j<=k` 為假,循環正常結束
  • 若 `i` 是素數,內層循環不會觸發 `break`,最終 `j == k+1`
  • 若 `i` 非素數,某處 `i%j==0` 觸發 `break`,此時 `j <= k`

2. `if(j >= k+1)` 的真實含義

等價於「內層循環完整遍歷完畢,未發現因數」,即判斷 `i` 為素數。

  • 素數:循環正常結束 → `j = k+1` → 條件成立 → 累加平方根
  • 非素數:中途 `break` → `j <= k` → 條件不成立 → 跳過

3. 為什麼用戶認為「j 應該到不了 k+1」

誤解了 `for` 循環的判斷順序:

  1. 執行循環體
  2. `j++`
  3. 判斷 `j<=k`,為假則退出,此時 `j` 已經是 `k+1`

這是 C 語言 `for` 循環的標準語義,非直觀預期。

代碼規範重構 (解決可讀性問題)

版本一:標誌變量法 (最清晰)

#include 
#include 

int main() {
    int n, i, j;
    double sum = 0.0;
    
    printf("輸入 n: ");
    scanf("%d", &n);
    
    for (i = 2; i <= n; i++) {  // 從 2 開始 (2 是素數)
        int isPrime = 1;        // 假設是素數
        int limit = (int)sqrt(i);
        
        for (j = 2; j <= limit; j++) {
            if (i % j == 0) {
                isPrime = 0;    // 發現因數,標記非素數
                break;
            }
        }
        
        if (isPrime) {
            sum += sqrt(i);
        }
    }
    
    printf("素數平方根和: %.4f\n", sum);
    return 0;
}

版本二:優化算法 (埃拉托斯特尼篩法 + 預計算平方根)

#include 
#include 
#include 
#include 

int main() {
    int n;
    printf("輸入 n (建議 <= 10^7): ");
    scanf("%d", &n);
    
    if (n < 2) { printf("0.0000\n"); return 0; }
    
    // 1. 篩法求素數
    bool *isPrime = (bool*)malloc((n+1) * sizeof(bool));
    for (int i = 2; i <= n; i++) isPrime[i] = true;
    
    for (int i = 2; i*i <= n; i++) {
        if (isPrime[i]) {
            for (int j = i*i; j <= n; j += i) isPrime[j] = false;
        }
    }
    
    // 2. 累加平方根
    double sum = 0.0;
    for (int i = 2; i <= n; i++) {
        if (isPrime[i]) sum += sqrt(i);
    }
    
    printf("素數平方根和: %.4f\n", sum);
    free(isPrime);
    return 0;
}

編程規範建議 (避免類似困惑)

問題代碼規範代碼理由
單字母變量 `i,j,k``num`, `divisor`, `limit`語義化命名,閱讀即文檔
無縮進/亂縮進統一 4 空格縮進結構一目了然
關鍵邏輯無註釋`// 判斷素數標誌`降低認知負荷
魔法數字 `k+1`常量 `PRIME_FLAG` / 布爾變量消除隱性知識
聲明與使用分離就近聲明 (C99+)減少作用域、提高局部性

編譯器建議

  • ✅ GCC/Clang:`gcc -std=c11 -Wall -Wextra -O2 -o prime prime.c`
  • ✅ MSVC:VS2019+ 支持 C11/C17,項目屬性 → C/C++ → 語言 → C 標準版本
  • ❌ Turbo C / VC6.0:不支持現代 C 標準,教學害大於利
  • 💡 在線編譯器:Compiler Explorer (查看匯編)、OnlineGDB (調試)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved