首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux C語言分解質因數:支持64位無符號長整型的完整實現

     編輯:關於C語言

Linux C語言分解質因數:支持64位無符號長整型的完整實現

本文提供一個高效的質因數分解程序,支持unsigned long long全範圍(2^64-1),包含邊界檢查、編譯鏈接技巧與性能分析。

完整代碼實現

#include 
#include 
#include 
#include 

int main(int argc, char **argv) {
    unsigned long long data = 0, i = 0, max = 0;

    // 參數檢查
    if (argc < 2) {
        printf("Usage: %s \n", argv[0]);
        return -1;
    }
    if (strlen(argv[1]) > 19) {  // ULLONG_MAX約20位
        printf("out of range\n");
        return -1;
    }

    data = atoll(argv[1]);

    // 特殊邊界:2^63-1 = 9223372036854775807
    if (9223372036854775807ULL == data && (argv[1][18]=='8' || argv[1][18]=='9')) {
        printf("out of range\n");
        return -1;
    }

    printf("data : %llu\n", data);

    // 試除法分解
    while (1) {
        max = sqrt(data);  // 動態更新上界
        for (i = 2; i <= max; i++) {
            if (data % i == 0) {
                data /= i;
                printf("%llu * ", i);
                fflush(stdout);  // 即時輸出
                break;
            }
        }
        if (i > max) {  // 剩餘data為質數
            printf("%llu\n", data);
            break;
        }
    }
    return 0;
}

關鍵技術點解析

1. 編譯鏈接數學庫

gcc -o factor factor.c -lm

原因:sqrt()定義在libm中,非標準C庫,需顯式鏈接-lm。

2. 類型選擇:unsigned long long

  • 範圍:0 ~ 18,446,744,073,709,551,615 (2^64-1)
  • 格式符:%llu (printf/scanf)
  • 轉換函數:atoll() / strtoull()

3. 試除法優化策略

  • 動態上界:每次除法後data變小,sqrt(data)顯著降低循環次數
  • 即時輸出:fflush(stdout)保證大數分解時逐步顯示結果
  • 早退機制:發現因子即break,避免繼續無效試除

4. 邊界處理細節

  • 字符串長度預檢(>19位直接拒絕)
  • ULLONG_MAX邊界值特殊判斷(atoll行為未定義)
  • 輸入驗證:非數字字符會被atoll忽略,建議用strtoull嚴格解析

性能與改進方向

輸入規模試除法耗時建議算法
< 10^12毫秒級試除法足夠
10^12 ~ 10^16秒~分鐘級Pollard's Rho
> 10^16極慢二次篩法/數域篩

進階版:Pollard's Rho 算法框架

// 核心思想:隨機多項式序列 + Floyd循環檢測 + GCD提取因子
unsigned long long pollard_rho(unsigned long long n) {
    if (n%2==0) return 2;
    if (is_prime(n)) return n;
    while(1) {
        unsigned long long c = rand()%(n-1)+1;
        unsigned long long x = rand()%n, y = x, d = 1;
        while(d==1) {
            x = (mul_mod(x,x,n)+c)%n;
            y = (mul_mod(y,y,n)+c)%n;
            y = (mul_mod(y,y,n)+c)%n;
            d = gcd(abs(x-y), n);
        }
        if(d!=n) return d;
    }
}
// 需配合 Miller-Rabin 質數測試、模乘防溢出

工程應用建議

  1. 輸入驗證:生產環境務必使用strtoull檢查errno與endptr
  2. 大數處理:超過10^14建議接入GMP庫(mpz_factor)
  3. 並行化:多線程分段試除或並行Pollard's Rho
  4. 結果格式化:收集因子統計冪次,輸出2^3 * 3 * 5^2形式

總結

試除法實現簡單、無依賴、適合中小規模數值分解。關鍵點在於-lm鏈接、unsigned long long類型使用、動態sqrt上界優化。面對大數分解需求,應升級為概率性算法並引入專業大數庫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved