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

大整數算法(2):初始化、銷毀、精度增長、復制、賦值、交換

     編輯:關於C語言

大整數庫維護算法:生命周期管理與基礎操作

上篇確立了數據結構,本文實現 bignum 的「出生、成長、複製、轉移、死亡」全生命周期函數,這些是所有高層算法調用最頻繁的基石,務必高效、健壯。

1. 初始化與銷毀

bn_init —— 輕量初始化(不分配內存)

void bn_init(bignum *x) {
    if (x) {
        x->sign = 1; x->alloc = 0; x->used = 0; x->dp = NULL;
    }
}

適用場景:臨時變量、結果參數、陣列批量初始化。後續調用 bn_grow 按需分配。

bn_init_size —— 初始化並預分配

int bn_init_size(bignum *x, size_t nlimbs) {
    if (nlimbs > BN_MAX_LIMB) return BN_EXCEED_MAX_LIMB;
    if (!x) return 0;
    bn_digit *p = (bn_digit*)BN_MALLOC(nlimbs * ciL);
    if (!p) return BN_MEMORY_ALLOCATE_FAIL;
    memset(p, 0, nlimbs * ciL);
    x->sign = 1; x->alloc = nlimbs; x->used = 0; x->dp = p;
    return 0;
}

適用場景:已知大致位數(如從字符串導入、固定長度運算),減少重複擴容。

bn_free —— 徹底銷毀

void bn_free(bignum *x) {
    if (x && x->dp) {
        memset(x->dp, 0, x->alloc * ciL); // 清敏感數據
        BN_FREE(x->dp);
        x->dp = NULL; // 防雙重釋放
    }
    if (x) { x->sign = 1; x->alloc = 0; x->used = 0; }
}

安全性: 清零內存防殘留敏感數據(私鑰等);置 NULL 防止 use-after-free。

2. 精度增長:bn_grow

int bn_grow(bignum *x, size_t nlimbs) {
    if (nlimbs > BN_MAX_LIMB) return BN_EXCEED_MAX_LIMB;
    if (nlimbs <= x->alloc) return 0; // 已足夠,無操作

    bn_digit *p = (bn_digit*)BN_MALLOC(nlimbs * ciL);
    if (!p) return BN_MEMORY_ALLOCATE_FAIL;
    memset(p, 0, nlimbs * ciL);
    if (x->dp) {
        memcpy(p, x->dp, x->alloc * ciL); // 保留原數據
        memset(x->dp, 0, x->alloc * ciL);
        BN_FREE(x->dp);
    }
    x->dp = p; x->alloc = nlimbs;
    return 0;
}

關鍵優化: 僅在需要時才重新分配,避免頻繁 malloc/free。調用者可預估大小調用 bn_init_size 或提前 bn_grow。

3. 復制操作:bn_copy

int bn_copy(bignum *x, const bignum *y) {
    if (x == y) return 0; // 同對象無需操作
    int ret; size_t nlimbs = (y->used == 0) ? 1 : y->used;
    BN_CHECK(bn_grow(x, nlimbs));
    memset(x->dp, 0, x->alloc * ciL);
    x->sign = y->sign; x->used = y->used;
    if (y->dp && y->used) memcpy(x->dp, y->dp, y->used * ciL);
clean:
    return ret;
}

深拷貝: 分配新內存,不共享 dp 指針。used==0 仍分配 1 位,保證 dp[0] 可寫。

4. 單精度賦值:bn_set_word

int bn_set_word(bignum *x, const bn_digit word) {
    int ret;
    BN_CHECK(bn_grow(x, 1));
    memset(x->dp, 0, ciL);
    x->dp[0] = word;
    x->used = (word != 0) ? 1 : 0;
    x->sign = 1; // 默認非負,負數調用後手動置 -1
clean:
    return ret;
}

常用於設置小常數(0, 1, 2, 模數等)。

5. 交換操作:bn_swap

void bn_swap(bignum *x, bignum *y) {
    int tmp_sign = x->sign;        x->sign = y->sign;        y->sign = tmp_sign;
    size_t tmp_alloc = x->alloc;   x->alloc = y->alloc;      y->alloc = tmp_alloc;
    size_t tmp_used = x->used;     x->used = y->used;        y->used = tmp_used;
    bn_digit *tmp_dp = x->dp;      x->dp = y->dp;            y->dp = tmp_dp;
}

O(1) 交換所有字段,用於算法中臨時變量輪換(如除法中被除數/除數交換)、避免拷貝開銷。

總結與下一步

函數用途時間複雜度備註
bn_init零成本初始化O(1)最常用
bn_init_size預分配O(n)n 為分配位數
bn_free釋放資源O(n)清零敏感數據
bn_grow按需擴容O(n)僅不足時分配
bn_copy深拷貝O(n)n 為源 used
bn_set_word單精度賦值O(1)小常數專用
bn_swap交換O(1)指針交換,無拷貝

下一篇將講解比較操作:絕對值比較、有符號比較、與單精度數比較,這是條件跳轉、排序、除法試商的基礎。

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