上一篇博文簡單談了大整數算法的一些最基本操作,接下來要介紹一些相對高級一點點的操作:比較操作。比較操作分成三種:絕對值比較,有符號數比較,多精度數和單精度數比較。
約定:所有的比較操作,如果 x > y,返回 1;x == y,返回 0;x < y,返回 -1。
★ 絕對值比較
絕對值比較操作只比較兩個大整數的絕對值大小,比較方法和十進制數的比較是相同的。先比較位數,位數大的絕對值更大,如果位數相同,從高位到低位依次比較兩個大整數中相同位的數位大小,如果比較到某一位時一個整數的該數位大於另一個整數中相同位置的數位,則該整數更大。
int bn_cmp_abs(const bignum *x, const bignum *y) { size_t i; if(x->used > y->used) return 1; if(x->used < y->used) return -1; //x 和 y 的位數相同,依次比較相同位的大小。 for(i = x->used; i > 0; i--) { if(x->dp[i - 1] > y->dp[i - 1]) return 1; if(x->dp[i - 1] < y->dp[i - 1]) return -1; } return 0; }
★ 有符號數比較
有符號數的比較比絕對值比較稍微復雜一點,但可以總結成一下幾類:
1. x 和 y 兩個數異號:非負數大於負數。
2. x 和 y 兩個數同號:若 x 和 y 都是非負整數,比較 x 和 y 的絕對值大小;若 x 和 y 都是負整數,比較 y 和 x 的絕對值大小。
第一種情況好理解,我就解釋一下第二種情況。
當 x >= 0 並且 y >= 0,若 x >= y(x < y),則有 |x| >= |y|(|x| < |y|),所以要比較 x 和 y 的絕對值大小。
當 x < 0 並且 y < 0,若 x >= y(x < y),則有 -x <= -y(-x > -y),即 |x| <= |y|(|x| > |y|),所以要比較 y 和 x 的絕對值大小(反方向執行無符號數比較)。
int bn_cmp_bn(const bignum *x, const bignum *y) { if(x->sign == 1 && y->sign == -1) return 1; if(y->sign == 1 && x->sign == -1) return -1; if(x->sign == 1) return bn_cmp_abs(x, y); else return bn_cmp_abs(y, x); }
★ 多精度數和單精度數比較
簡單來說就是將一個大整數與一個有符號的單精度數(bn_sint類型)進行比較。有了前面的大整數與大整數之間的有符號比較操作,這裡就不需要再寫一個新的操作了,直接把有符號的單精度數賦值給一個臨時的大整數類型變量 t,然後調用bn_cmp_bn函數進行比較。雖然這種帶有欺騙性的把戲在一定程度上會損失一點點性能,但可以讓編碼和計算變得相對簡單。
int bn_cmp_int(const bignum *x, const bn_sint y) { bignum t[1]; bn_digit p[1]; p[0] = (y >= 0) ? y : -y; t->sign = (y >= 0) ? 1 : -1; t->used = (y == 0) ? 0 : 1; //注意 bignum 為 0 時,規定 used = 0. t->alloc = 1; t->dp = p; return bn_cmp_bn(x, t); }
★ 總結
比較操作雖然簡單,不過在一開始實現的時候還是犯了好幾個低級錯誤,歸根結底還是沒有考慮好所有情況,編碼的時候也不夠仔細,所以還是那句老話:細節決定成敗。下一篇文章將介紹更高級點的操作:位設置操作。
【回到本系列目錄】
版權聲明
原創博文,轉載必須包含本聲明,保持本文完整,並以超鏈接形式注明作者Starrybird和本文原始地址:http://www.cnblogs.com/starrybird/p/4354703.html