模運算
整數取模實際是基於除法運算的結果,即求餘數的過程,把商排除在外後得到的結果。根據已經得到的除法運算結果進行篩選結果即可。
/*
模數運算
a 被模數
b 模數
c 模值
*/
int modHBInt(HBigInt *a, HBigInt *b, HBigInt *c){
HBigInt tc;
//模數不能爲0
if(0 == b->length || (1 == b->length && 0 == b->pBigInt[0])) return -1;
//模數爲1,則模值等於被模數
if(1 == b->length && 1 == b->pBigInt[0]) {
setZeroHBInt(c);
hbi_add_int(c,0);
return RETURN_OK_BINT;
}
if(-1 == compareHBInt(a,b)) { //模數大於被模數,模值爲被模數
assignHBInt(c,a);
return RETURN_OK_BINT;
}
//初始化臨時變量
initHBInt(&tc,INITIAL_BINT);
divHBInt(a, b, &tc, c);
// 回收臨時變量空間
deleteHBInt(&tc);
return RETURN_OK_BINT;
}
模冪運算
由於底數和指數都是大整數,所以採用一般的計算方式(計算冪值後利用除法進行取模)存在嚴重的效率地下問題,因此在選擇算法時必須考慮快速和已處理兩部分的因素。在處理該算法時,最核心的部分是降冪運算,所以採用了平方乘取模的原理。
算法流程如下:
輸入:3個B進制(位數n、t、p)的大整數x(底數)、y(冪數)、z(模數) 輸出:B進制的模值r(初始化r=1) |
1. 判斷非一般情況下模冪結果: 1.1 z == 0,則返回錯誤碼 RETURN_FAILE_BINT 1.2 z == 1,則r = 0,實際上r = xy ,因爲這樣的計算失去取模的意義 1.3 y == 1,則r = x % z,即普通的取模運算 1.4 y == 0,則r=1 2. i從t到0 2.1 y是奇數,則r = r * x % z 2.2 x = x2 % z 2.3 y = y / 2 2.4 根據當前y的長度(位數)來遞減i的值 3. 返回r |
/*
模數運算
a 被模數
p 指數
b 模數
c 模值
*/
int modPowerHBInt(HBigInt *a, HBigInt *p, HBigInt *b, HBigInt *c){
HBigInt ta,ta_1,tp,tc,tc_1,demo_one;
// 模數爲0
if(0 == b->length || (1 == b->length && 0 == b->pBigInt[0])) return -1;
// 模數爲1,則模值等於被模數,因爲沒有計算的意義,所以自定義爲0
if(1 == b->length && 1 == b->pBigInt[0]) {
setZeroHBInt(c);
hbi_add_int(c,0);
return RETURN_OK_BINT;
}
if( 1 == p->length && 1 == p->pBigInt[0] ) return modHBInt(a,b,c);
else if ( (1 == p->length && 0 == p->pBigInt[0]) || 0 == p->length) {
// 指數爲0
setZeroHBInt(c);
hbi_add_int(c,1);
return RETURN_OK_BINT;
} else {
setZeroHBInt(c);
hbi_add_int(c,1);
initHBInt(&ta,INITIAL_BINT);
initHBInt(&ta_1,INITIAL_BINT);
initHBInt(&tp,INITIAL_BINT);
initHBInt(&tc,INITIAL_BINT);
initHBInt(&tc_1,INITIAL_BINT);
initHBInt(&demo_one,INITIAL_BINT);
initHBInt(&tp,INITIAL_BINT);
extendHBInt(&tc,c->length);
extendHBInt(&ta_1,c->length);
// 初始化單位1
setZeroHBInt(&demo_one);
hbi_add_int(&demo_one,1);
// 賦值臨時變量
assignHBInt(&tp,p);
assignHBInt(&ta,a);
extendHBInt(&tc,c->length);
extendHBInt(&ta_1,ta.length + ta.length);
// 平方乘取摸
while(tp.length){
if (tp.pBigInt[0] & 0x1){
mulHBInt(c,c,&ta);
assignHBInt(&tc,c);
modHBInt(&tc,b,c);
}
mulHBInt(&ta_1,&ta,&ta);
modHBInt(&ta_1,b,&ta);
// 降冪
Right_shift_bit(&tc_1, &tp);
assignHBInt(&tp,&tc_1);
trimHBInt(&tp); //去除高位無效的0
}
}
// 回收臨時變量空間
deleteHBInt(&ta);
deleteHBInt(&ta_1);
deleteHBInt(&tp);
deleteHBInt(&tc);
deleteHBInt(&tc_1);
deleteHBInt(&demo_one);
return RETURN_OK_BINT;
}