信息安全——大整数包的设计!

来源:互联网 发布:脸基尼 知乎 编辑:程序博客网 时间:2024/04/27 23:33

 大整数运算包的设计与实现

1.问题描述

大整数运算是现代密码学算法实现的基础,重要性不言而喻。大整数我们指的是二进制位512、1024和2048的数,一般的语言不支持。

2.基本要求

以类库头文件的形式实现。

3.实现提示

   在选择了大整数的存储结构之后,主要实现以下运算:

①    模加;

②    模减;

③    模乘;

④    模整除;

⑤    模取余。这五种运算模拟手算实现。

⑥    幂模:利用“平方-乘法”算法实现。

⑦    GCD:利用欧几里得算法实现。

⑧    乘法逆: 利用扩展的欧几里得算法实现。

⑨    素数判定与生成:概率性素数产生方法产生的数仅仅是伪素数,其缺点在于,尽管其产生合数的可能性很小,但是这种可能性仍然存在:其优点是产生的伪素数没有规律性,而且产生的速度也比较快。此类方法是生成大素数的主要方法,其中较著名的算法有:Miller Rabin算法、Solovay-Strassen算法等。本文讨论Miller  Rabin算法。

Miller Rabin素性测试法是在实际中应用非常广的一种素性测试方案,可以用来判定某随机数是否为素数。其定义如下:

设n>2是一个奇数,设n-1=2sm,其中s是非负整数,m>0是奇数,设0<b<n,如果

bm≡-1(modn),

或者存在一个r,0≤r<s,使得

b 2^r m≡-1(modn)

则称n通过以b为基的Miller-Rabin测试。

可以利用Miller-Rabin素性测试算法来随机生成大素数,随即生成一个奇数n>2,随即均匀的选取序列b1,b2...,bk∈{1,2,...,n-1},对n进行k次Miller-Rabin素性测试,如果每次输出都为“n可能是素数”,则n是合数的概率小于 1/4k当k足够大时,1/4k是一个十分小的数。

    同学们在具体实现时,为了提高速度最好以空间换时间,在主程序运行前先构造一个大素数表。


具体的代码如下:

BigInteger.h

#pragma once#include <cstring>#include <string>#include <algorithm>#include <assert.h>#include <ctime>#include <iostream>using namespace std;const int maxLength = 512;const int primeLength = 50;const int primesBelow2000[303] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293,307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397,401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499,503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599,601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691,701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797,809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887,907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097,1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193,1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297,1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499,1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597,1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699,1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789,1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999 };class BigInteger{typedef unsigned char byte;public:BigInteger(void);BigInteger(__int64 value);BigInteger(unsigned __int64 value);BigInteger(const BigInteger &bi);BigInteger(string value, int radix);BigInteger(byte inData[], int inLen);BigInteger(unsigned int inData[], int inLen);    BigInteger operator -();BigInteger operator =(const BigInteger &bi2);BigInteger operator +(BigInteger &bi2);BigInteger operator -(BigInteger bi2);BigInteger operator /(BigInteger bi2);BigInteger operator *(BigInteger bi2);void singleByteDivide(BigInteger &bi1, BigInteger &bi2, BigInteger &outQuotient, BigInteger &outRemainder);void multiByteDivide(BigInteger &bi1, BigInteger &bi2, BigInteger &outQuotient, BigInteger &outRemainder);BigInteger operator %(BigInteger bi2);BigInteger operator +=(BigInteger bi2);BigInteger operator -=(BigInteger bi2);    int bitCount();BigInteger modPow(BigInteger exp, BigInteger n);friend ostream& operator<<(ostream& output, BigInteger &bi1);friend BigInteger GetPrime();friend bool Miller_Robin(BigInteger &bi1);friend BigInteger MultipInverse(BigInteger &bi1, BigInteger &n);friend BigInteger extended_euclidean(BigInteger n, BigInteger m, BigInteger &x, BigInteger &y); friend BigInteger MultipInverse(BigInteger &bi1, BigInteger &n);   //求乘法逆friend BigInteger Gcd(BigInteger &bi1, BigInteger &bi2);   //求最大公约数BigInteger BarrettReduction(BigInteger x, BigInteger n, BigInteger constant);bool operator >=(BigInteger bi2){return ((*this) == bi2 || (*this) > bi2);}bool operator >(BigInteger bi2);bool operator ==(BigInteger bi2);bool operator !=(BigInteger bi2);int shiftRight(unsigned int buffer[], int bufLen, int shiftVal);BigInteger operator <<(int shiftVal);int shiftLeft(unsigned int buffer[], int bufLen, int shiftVal);bool operator <(BigInteger bi2);string DecToHex(unsigned int value, string format);string ToHexString();public:~BigInteger(void);public:int dataLength;// number of actual chars usedunsigned int *data;};

BigInteger.cpp

#include "BigInteger.h"BigInteger::BigInteger(void)   //默认的构造函数: dataLength(0), data(0){data = new unsigned int[maxLength];memset(data, 0, maxLength * sizeof(unsigned int));dataLength = 1;}BigInteger::BigInteger(__int64 value)   //用一个64位的值来初始化大数{data = new unsigned int[maxLength];memset(data, 0, maxLength * sizeof(unsigned int));   //先清零__int64 tempVal = value;dataLength = 0;while (value != 0 && dataLength < maxLength){data[dataLength] = (unsigned int)(value & 0xFFFFFFFF);   //取低位value = value >> 32;   //进位dataLength++;}if (tempVal > 0)         // overflow check for +ve value{if (value != 0 || (data[maxLength - 1] & 0x80000000) != 0)assert(false);}else if (tempVal < 0)    // underflow check for -ve value{if (value != -1 || (data[dataLength - 1] & 0x80000000) == 0)assert(false);}if (dataLength == 0)dataLength = 1;}BigInteger::BigInteger(unsigned __int64 value)   //用一个无符号的64位整数来初始化大数{data = new unsigned int[maxLength];memset(data, 0, maxLength * sizeof(unsigned int));dataLength = 0;while (value != 0 && dataLength < maxLength){data[dataLength] = (unsigned int)(value & 0xFFFFFFFF);value >>= 32;dataLength++;}if (value != 0 || (data[maxLength - 1] & 0x80000000) != 0)assert(false);if (dataLength == 0)   //防止输入的value=0dataLength = 1;}BigInteger::BigInteger(const BigInteger &bi)   //用大数初始化大数{data = new unsigned int[maxLength];dataLength = bi.dataLength;for (int i = 0; i < maxLength; i++)   //考虑到有负数的情况,所以每一位都要复制data[i] = bi.data[i];}BigInteger::~BigInteger(void){if (data != NULL){delete []data;}}BigInteger::BigInteger(string value, int radix)   //输入转换函数,将字符串转换成对应进制的大数{   //一般不处理负数BigInteger multiplier((__int64)1);BigInteger result;transform(value.begin(), value.end(), value.begin(), toupper);   //将小写字母转换成为大写int limit = 0;if (value[0] == '-')   limit = 1;for (int i = value.size() - 1; i >= limit; i--){int posVal = (int)value[i];if (posVal >= '0' && posVal <= '9')  //将字符转换成数字posVal -= '0';else if (posVal >= 'A' && posVal <= 'Z')posVal = (posVal - 'A') + 10;elseposVal = 9999999;       // arbitrary large 输入别的字符if (posVal >= radix)   //不能大于特定的进制,否则终止{assert(false);}else{result = result + (multiplier * BigInteger((__int64)posVal));if ((i - 1) >= limit)   //没有到达尾部multiplier = multiplier * BigInteger((__int64)radix);}}if (value[0] == '-')   //符号最后再处理   result = -result;if (value[0] == '-')     //输入为负数,但得到的结果为正数,可能溢出了{if ((result.data[maxLength - 1] & 0x80000000) == 0)   assert(false);}else    //或者说,输入为正数,得到的结果为负数,也可能溢出了{if ((result.data[maxLength - 1] & 0x80000000) != 0)  assert(false);}data = new unsigned int[maxLength];//memset(data, 0, maxLength * sizeof(unsigned int));for (int i = 0; i < maxLength; i++)data[i] = result.data[i];dataLength = result.dataLength;}BigInteger::BigInteger(byte inData[], int inLen)   //用一个char类型的数组来初始化大数{dataLength = inLen >> 2;   //一个unsigned int占32位,而一个unsigned char只占8位//因此dataLength应该是至少是inLen/4,不一定整除int leftOver = inLen & 0x3;  //取最低两位的数值,为什么要这样干呢?实际上是为了探测len是不是4的倍数,好确定dataLength的长度if (leftOver != 0)    //不能整除的话,dataLength要加1dataLength++;if (dataLength > maxLength)assert(false);data = new unsigned int[maxLength];memset(data, 0, maxLength * sizeof(unsigned int));for (int i = inLen - 1, j = 0; i >= 3; i -= 4, j++)   {data[j] = (unsigned int)((inData[i - 3] << 24) + (inData[i - 2] << 16) + (inData[i - 1] << 8) + inData[i]);//我们知道:一个unsigned int占32位,而一个unsigned char只占8位,因此四个unsigned char才能组成一个unsigned int//因此取inData[i - 3]为前32-25位,inData[i - 2]为前24-17~~~//i % 4 = 0 or 1 or 2 or 3 余0表示恰好表示完}if (leftOver == 1)data[dataLength - 1] = (unsigned int)inData[0];else if (leftOver == 2)data[dataLength - 1] = (unsigned int)((inData[0] << 8) + inData[1]);else if (leftOver == 3)data[dataLength - 1] = (unsigned int)((inData[0] << 16) + (inData[1] << 8) + inData[2]);while (dataLength > 1 && data[dataLength - 1] == 0)dataLength--;}BigInteger::BigInteger(unsigned int inData[], int inLen)   //用一个unsigned int型数组初始化大数{dataLength = inLen;if (dataLength > maxLength)assert(false);data = new unsigned int[maxLength];memset(data, 0, maxLength * sizeof(maxLength));for (int i = dataLength - 1, j = 0; i >= 0; i--, j++)data[j] = inData[i];while (dataLength > 1 && data[dataLength - 1] == 0)dataLength--;}BigInteger BigInteger::operator *(BigInteger bi2)   //乘法的重载{BigInteger bi1(*this);int lastPos = maxLength - 1;bool bi1Neg = false, bi2Neg = false;//首先对两个乘数取绝对值try{if ((this->data[lastPos] & 0x80000000) != 0)     //bi1为负数{bi1Neg = true; bi1 = -bi1;}if ((bi2.data[lastPos] & 0x80000000) != 0)     //bi2为负数{bi2Neg = true; bi2 = -bi2;}}catch (...) { }BigInteger result;//绝对值相乘try{for (int i = 0; i < bi1.dataLength; i++){if (bi1.data[i] == 0) continue;unsigned __int64 mcarry = 0;for (int j = 0, k = i; j < bi2.dataLength; j++, k++){// k = i + junsigned __int64 val = ((unsigned __int64)bi1.data[i] * (unsigned __int64)bi2.data[j]) + (unsigned __int64)result.data[k] + mcarry;result.data[k] = (unsigned __int64)(val & 0xFFFFFFFF);   //取低位mcarry = (val >> 32);   //进位}if (mcarry != 0)result.data[i + bi2.dataLength] = (unsigned int)mcarry;}}catch (...){assert(false);}result.dataLength = bi1.dataLength + bi2.dataLength;if (result.dataLength > maxLength)result.dataLength = maxLength;while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)result.dataLength--;// overflow check (result is -ve)溢出检查if ((result.data[lastPos] & 0x80000000) != 0)  //结果为负数{if (bi1Neg != bi2Neg && result.data[lastPos] == 0x80000000)    //两乘数符号不同{// handle the special case where multiplication produces// a max negative number in 2's complement.if (result.dataLength == 1)return result;else{bool isMaxNeg = true;for (int i = 0; i < result.dataLength - 1 && isMaxNeg; i++){if (result.data[i] != 0)isMaxNeg = false;}if (isMaxNeg)return result;}}assert(false);}//两乘数符号不同,结果为负数if (bi1Neg != bi2Neg)return -result;return result;}BigInteger BigInteger::operator =(const BigInteger &bi2){if (&bi2 == this){return *this;}if (data != NULL){delete []data;data = NULL;}data = new unsigned int[maxLength];memset(data, 0, maxLength * sizeof(unsigned int));dataLength = bi2.dataLength;for (int i = 0; i < maxLength; i++)data[i] = bi2.data[i];return *this;}BigInteger BigInteger::operator +(BigInteger &bi2){int lastPos = maxLength - 1;bool bi1Neg = false, bi2Neg = false;BigInteger bi1(*this);BigInteger result;    if ((this->data[lastPos] & 0x80000000) != 0)     //bi1为负数      bi1Neg = true; if ((bi2.data[lastPos] & 0x80000000) != 0)     //bi2为负数bi2Neg = true; if(bi1Neg == false && bi2Neg == false)   //bi1与bi2都是正数{result.dataLength = (this->dataLength > bi2.dataLength) ? this->dataLength : bi2.dataLength;__int64 carry = 0;for (int i = 0; i < result.dataLength; i++)   //从低位开始,逐位相加{__int64 sum = (__int64)this->data[i] + (__int64)bi2.data[i] + carry;carry = sum >> 32;   //进位result.data[i] = (unsigned int)(sum & 0xFFFFFFFF);  //取低位结果}if (carry != 0 && result.dataLength < maxLength){result.data[result.dataLength] = (unsigned int)(carry);result.dataLength++;}while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)result.dataLength--;//溢出检查if ((this->data[lastPos] & 0x80000000) == (bi2.data[lastPos] & 0x80000000) &&(result.data[lastPos] & 0x80000000) != (this->data[lastPos] & 0x80000000)){assert(false);}return result;}//关键在于,负数全部要转化成为正数来做if(bi1Neg == false && bi2Neg == true)   //bi1正,bi2负{BigInteger bi3 = -bi2;if(bi1 > bi3){ result = bi1 - bi3;  return result;}else{ result = -(bi3 - bi1); return result;}}if(bi1Neg == true && bi2Neg == false)  //bi1负,bi2正{        BigInteger bi3 = -bi1;if(bi3 > bi2){ result = -(bi3 - bi2); return result;}else{ result = bi2 - bi3; return result;}}    if(bi1Neg == true && bi2Neg == true)  //bi1负,bi2负{result = - ((-bi1) + (-bi2));return result;}}BigInteger BigInteger::operator -(){//逐位取反并+1if (this->dataLength == 1 && this->data[0] == 0)return *this;BigInteger result(*this);for (int i = 0; i < maxLength; i++)result.data[i] = (unsigned int)(~(this->data[i]));   //取反__int64 val, carry = 1;int index = 0;while (carry != 0 && index < maxLength)  //+1;{val = (__int64)(result.data[index]);val++;   //由于值加了1个1,往前面的进位最多也只是1个1,因此val++就完了result.data[index] = (unsigned int)(val & 0xFFFFFFFF);   //取低位部分carry = val >> 32;   //进位index++;}if ((this->data[maxLength - 1] & 0x80000000) == (result.data[maxLength - 1] & 0x80000000))result.dataLength = maxLength;while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)result.dataLength--;return result;}BigInteger BigInteger::modPow(BigInteger exp, BigInteger n)   //求this^exp mod n{if ((exp.data[maxLength - 1] & 0x80000000) != 0)   //指数是负数return BigInteger((__int64)0);BigInteger resultNum((__int64)1);BigInteger tempNum;bool thisNegative = false;if ((this->data[maxLength - 1] & 0x80000000) != 0)   //底数是负数{tempNum = -(*this) % n;thisNegative = true;}elsetempNum = (*this) % n;  //保证(tempNum * tempNum) < b^(2k)if ((n.data[maxLength - 1] & 0x80000000) != 0)   //n为负n = -n;//计算 constant = b^(2k) / m//constant主要用于后面的Baeert Reduction算法BigInteger constant;int i = n.dataLength << 1;constant.data[i] = 0x00000001;constant.dataLength = i + 1;constant = constant / n;int totalBits = exp.bitCount();int count = 0;//平方乘法算法for (int pos = 0; pos < exp.dataLength; pos++){unsigned int mask = 0x01;for (int index = 0; index < 32; index++){if ((exp.data[pos] & mask) != 0)  //某一个bit不为0resultNum = BarrettReduction(resultNum * tempNum, n, constant);//resultNum = resultNum * tempNum mod nmask <<= 1; //不断左移tempNum = BarrettReduction(tempNum * tempNum, n, constant);//tempNum = tempNum * tempNum mod nif (tempNum.dataLength == 1 && tempNum.data[0] == 1){if (thisNegative && (exp.data[0] & 0x1) != 0)    //指数为奇数return -resultNum;return resultNum;}count++;if (count == totalBits)break;}}if (thisNegative && (exp.data[0] & 0x1) != 0)    //底数为负数,指数为奇数return -resultNum;return resultNum;}int BigInteger::bitCount()   //计算字节数{while (dataLength > 1 && data[dataLength - 1] == 0)dataLength--;unsigned int value = data[dataLength - 1];unsigned int mask = 0x80000000;int bits = 32;while (bits > 0 && (value & mask) == 0)   //计算最高位的bit{bits--;mask >>= 1;}bits += ((dataLength - 1) << 5);   //余下的位都有32bit//左移5位,相当于乘以32,即2^5return bits;}BigInteger BigInteger::BarrettReduction(BigInteger x, BigInteger n, BigInteger constant){//算法,Baeert Reduction算法,在计算大规模的除法运算时很有优势//原理如下//Z mod N=Z-[Z/N]*N=Z-{[Z/b^(n-1)]*[b^2n/N]/b^(n+1)}*N=Z-q*N//q=[Z/b^(n-1)]*[b^2n/N]/b^(n+1)//其中,[]表示取整运算,A^B表示A的B次幂int k = n.dataLength,kPlusOne = k + 1,kMinusOne = k - 1;BigInteger q1;// q1 = x / b^(k-1)for (int i = kMinusOne, j = 0; i < x.dataLength; i++, j++)q1.data[j] = x.data[i];q1.dataLength = x.dataLength - kMinusOne;if (q1.dataLength <= 0)q1.dataLength = 1;BigInteger q2 = q1 * constant;BigInteger q3;// q3 = q2 / b^(k+1)for (int i = kPlusOne, j = 0; i < q2.dataLength; i++, j++)q3.data[j] = q2.data[i];q3.dataLength = q2.dataLength - kPlusOne;if (q3.dataLength <= 0)q3.dataLength = 1;// r1 = x mod b^(k+1)// i.e. keep the lowest (k+1) wordsBigInteger r1;int lengthToCopy = (x.dataLength > kPlusOne) ? kPlusOne : x.dataLength;for (int i = 0; i < lengthToCopy; i++)r1.data[i] = x.data[i];r1.dataLength = lengthToCopy;// r2 = (q3 * n) mod b^(k+1)// partial multiplication of q3 and nBigInteger r2;for (int i = 0; i < q3.dataLength; i++){if (q3.data[i] == 0) continue;unsigned __int64 mcarry = 0;int t = i;for (int j = 0; j < n.dataLength && t < kPlusOne; j++, t++){// t = i + junsigned __int64 val = ((unsigned __int64)q3.data[i] * (unsigned __int64)n.data[j]) +(unsigned __int64)r2.data[t] + mcarry;r2.data[t] = (unsigned int)(val & 0xFFFFFFFF);mcarry = (val >> 32);}if (t < kPlusOne)r2.data[t] = (unsigned int)mcarry;}r2.dataLength = kPlusOne;while (r2.dataLength > 1 && r2.data[r2.dataLength - 1] == 0)r2.dataLength--;r1 -= r2;if ((r1.data[maxLength - 1] & 0x80000000) != 0)        // negative{BigInteger val;val.data[kPlusOne] = 0x00000001;val.dataLength = kPlusOne + 1;r1 += val;}while (r1 >= n)r1 -= n;return r1;}bool BigInteger::operator >(BigInteger bi2){int pos = maxLength - 1;BigInteger bi1(*this);// bi1 is negative, bi2 is positiveif ((bi1.data[pos] & 0x80000000) != 0 && (bi2.data[pos] & 0x80000000) == 0)return false;// bi1 is positive, bi2 is negativeelse if ((bi1.data[pos] & 0x80000000) == 0 && (bi2.data[pos] & 0x80000000) != 0)return true;// same signint len = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;for (pos = len - 1; pos >= 0 && bi1.data[pos] == bi2.data[pos]; pos--) ;if (pos >= 0){if (bi1.data[pos] > bi2.data[pos])return true;return false;}return false;}bool BigInteger::operator ==(BigInteger bi2){if (this->dataLength != bi2.dataLength)return false;for (int i = 0; i < this->dataLength; i++){if (this->data[i] != bi2.data[i])return false;}return true;}bool BigInteger::operator !=(BigInteger bi2){if(this->dataLength != bi2.dataLength)return true;for(int i = 0; i < this->dataLength; i++){if(this->data[i] != bi2.data[i])return true;}return false;}BigInteger BigInteger::operator %(BigInteger bi2){BigInteger bi1(*this);BigInteger quotient;BigInteger remainder(bi1);int lastPos = maxLength - 1;bool dividendNeg = false;if ((bi1.data[lastPos] & 0x80000000) != 0)     // bi1 negative{bi1 = -bi1;dividendNeg = true;}if ((bi2.data[lastPos] & 0x80000000) != 0)     // bi2 negativebi2 = -bi2;if (bi1 < bi2){return remainder;}else{if (bi2.dataLength == 1)singleByteDivide(bi1, bi2, quotient, remainder);   //bi2只占一个位置时,用singleByteDivide更快elsemultiByteDivide(bi1, bi2, quotient, remainder);   //bi2占多个位置时,用multiByteDivide更快if (dividendNeg)return -remainder;return remainder;}}void BigInteger::singleByteDivide(BigInteger &bi1, BigInteger &bi2,  BigInteger &outQuotient, BigInteger &outRemainder){//outQuotient商,outRemainder余数unsigned int result[maxLength];   //用来存储结果memset(result, 0, sizeof(unsigned int) * maxLength);int resultPos = 0;for (int i = 0; i < maxLength; i++)   //将bi1复制至outRemainderoutRemainder.data[i] = bi1.data[i];outRemainder.dataLength = bi1.dataLength;while (outRemainder.dataLength > 1 && outRemainder.data[outRemainder.dataLength - 1] == 0)outRemainder.dataLength--;unsigned __int64 divisor = (unsigned __int64)bi2.data[0];int pos = outRemainder.dataLength - 1;unsigned __int64 dividend = (unsigned __int64)outRemainder.data[pos];   //取最高位的数值if (dividend >= divisor)   //被除数>除数{unsigned __int64 quotient = dividend / divisor;result[resultPos++] = (unsigned __int64)quotient;   //结果outRemainder.data[pos] = (unsigned __int64)(dividend % divisor);   //余数}pos--;while (pos >= 0){dividend = ((unsigned __int64)outRemainder.data[pos + 1] << 32) + (unsigned __int64)outRemainder.data[pos];   //前一位的余数和这一位的值相加unsigned __int64 quotient = dividend / divisor;   //得到结果result[resultPos++] = (unsigned int)quotient;   //结果取低位outRemainder.data[pos + 1] = 0;   //前一位的余数清零outRemainder.data[pos--] = (unsigned int)(dividend % divisor);   //得到这一位的余数}outQuotient.dataLength = resultPos;   //商的长度是resultPos的长度int j = 0;for (int i = outQuotient.dataLength - 1; i >= 0; i--, j++)  //将商反转过来 outQuotient.data[j] = result[i];for (; j < maxLength; j++)   //商的其余位都要置0outQuotient.data[j] = 0;while (outQuotient.dataLength > 1 && outQuotient.data[outQuotient.dataLength - 1] == 0)outQuotient.dataLength--;if (outQuotient.dataLength == 0)outQuotient.dataLength = 1;while (outRemainder.dataLength > 1 && outRemainder.data[outRemainder.dataLength - 1] == 0)outRemainder.dataLength--;}void BigInteger::multiByteDivide(BigInteger &bi1, BigInteger &bi2, BigInteger &outQuotient, BigInteger &outRemainder){unsigned int result[maxLength];memset(result, 0, sizeof(unsigned int) * maxLength);   //结果置零 int remainderLen = bi1.dataLength + 1;   //余数长度unsigned int *remainder = new unsigned int[remainderLen];memset(remainder, 0, sizeof(unsigned int) * remainderLen);   //余数置零unsigned int mask = 0x80000000;unsigned int val = bi2.data[bi2.dataLength - 1];int shift = 0, resultPos = 0;while (mask != 0 && (val & mask) == 0){shift++; mask >>= 1;}   //最高位从高到低找出shift个0位for (int i = 0; i < bi1.dataLength; i++)remainder[i] = bi1.data[i];   //将bi1复制到remainder之中this->shiftLeft(remainder, remainderLen, shift);   //remainder左移shift位bi2 = bi2 << shift;   //向左移shift位,将空位填满//由于两个数都扩大了相同的倍数,所以结果不变int j = remainderLen - bi2.dataLength;   //j表示两个数长度的差值,也是要计算的次数int pos = remainderLen - 1;   //pos指示余数的最高位的位置,现在pos=bi1.dataLength//以下的步骤并没有别的意思,主要是用来试商unsigned __int64 firstDivisorByte = bi2.data[bi2.dataLength - 1];   //第一个除数unsigned __int64 secondDivisorByte = bi2.data[bi2.dataLength - 2];  //第二个除数 int divisorLen = bi2.dataLength + 1;   //除数的长度unsigned int *dividendPart = new unsigned int[divisorLen];   //起名为除数的部分memset(dividendPart, 0, sizeof(unsigned int) * divisorLen);while (j > 0){unsigned __int64 dividend = ((unsigned __int64)remainder[pos] << 32) + (unsigned __int64)remainder[pos - 1];   //取余数的高两位unsigned __int64 q_hat = dividend / firstDivisorByte;   //得到一个商unsigned __int64 r_hat = dividend % firstDivisorByte;   //以及一个余数bool done = false;   //表示没有做完while (!done){done = true;if (q_hat == 0x100000000 || (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder[pos - 2]))   //这里主要用来调整商的大小 //(q_hat * secondDivisorByte) > ((r_hat << 32) + remainder[pos - 2]))是害怕上的商过大,减之后变为负数        //商q_hat也不能超过32bit{q_hat--;   //否则的话,就商小一点,余数大一点r_hat += firstDivisorByte;if (r_hat < 0x100000000)   //如果余数小于32bit,就继续循环done = false;}}for (int h = 0; h < divisorLen; h++)   //取被除数的高位部分,高位部分长度与除数长度一致dividendPart[h] = remainder[pos - h];BigInteger kk(dividendPart, divisorLen);BigInteger ss = bi2 * BigInteger((__int64)q_hat);while (ss > kk)   //调节商的大小{q_hat--;ss -= bi2;}BigInteger yy = kk - ss;   //得到余数for (int h = 0; h < divisorLen; h++)  //将yy高位和remainder低位拼接起来,得到余数remainder[pos - h] = yy.data[bi2.dataLength - h];   //取得真正的余数result[resultPos++] = (unsigned int)q_hat;pos--;j--;}outQuotient.dataLength = resultPos;int y = 0;for (int x = outQuotient.dataLength - 1; x >= 0; x--, y++)   //将商反转过来outQuotient.data[y] = result[x];for (; y < maxLength; y++)   //商的其余位都要置0outQuotient.data[y] = 0;while (outQuotient.dataLength > 1 && outQuotient.data[outQuotient.dataLength - 1] == 0)outQuotient.dataLength--;if (outQuotient.dataLength == 0)outQuotient.dataLength = 1;outRemainder.dataLength = this->shiftRight(remainder, remainderLen, shift);for (y = 0; y < outRemainder.dataLength; y++)outRemainder.data[y] = remainder[y];for (; y < maxLength; y++)outRemainder.data[y] = 0;delete []remainder;delete []dividendPart;}int BigInteger::shiftRight(unsigned int buffer[], int bufferLen,int shiftVal)   //右移操作{//自己用图画模拟一下移位操作,就能很快明白意义了int shiftAmount = 32;int invShift = 0;int bufLen = bufferLen;while (bufLen > 1 && buffer[bufLen - 1] == 0)bufLen--;for (int count = shiftVal; count > 0; ){if (count < shiftAmount){shiftAmount = count;invShift = 32 - shiftAmount;}unsigned __int64 carry = 0;for (int i = bufLen - 1; i >= 0; i--){unsigned __int64 val = ((unsigned __int64)buffer[i]) >> shiftAmount;val |= carry;carry = ((unsigned __int64)buffer[i]) << invShift;buffer[i] = (unsigned int)(val);}count -= shiftAmount;}while (bufLen > 1 && buffer[bufLen - 1] == 0)bufLen--;return bufLen;}BigInteger BigInteger::operator <<(int shiftVal){BigInteger result(*this);result.dataLength = shiftLeft(result.data, maxLength, shiftVal);return result;}int BigInteger::shiftLeft(unsigned int buffer[], int bufferLen, int shiftVal){int shiftAmount = 32;int bufLen = bufferLen;while (bufLen > 1 && buffer[bufLen - 1] == 0)bufLen--;for (int count = shiftVal; count > 0; ){if (count < shiftAmount)shiftAmount = count;unsigned __int64 carry = 0;for (int i = 0; i < bufLen; i++){unsigned __int64 val = ((unsigned __int64)buffer[i]) << shiftAmount;val |= carry;buffer[i] = (unsigned int)(val & 0xFFFFFFFF);carry = val >> 32;}if (carry != 0){if (bufLen + 1 <= bufferLen){buffer[bufLen] = (unsigned int)carry;bufLen++;}}count -= shiftAmount;}return bufLen;}bool BigInteger::operator <(BigInteger bi2){BigInteger bi1(*this);int pos = maxLength - 1;// bi1 is negative, bi2 is positiveif ((bi1.data[pos] & 0x80000000) != 0 && (bi2.data[pos] & 0x80000000) == 0)return true;// bi1 is positive, bi2 is negativeelse if ((bi1.data[pos] & 0x80000000) == 0 && (bi2.data[pos] & 0x80000000) != 0)return false;// same signint len = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;for (pos = len - 1; pos >= 0 && bi1.data[pos] == bi2.data[pos]; pos--) ;if (pos >= 0){if (bi1.data[pos] < bi2.data[pos])return true;return false;}return false;}BigInteger BigInteger::operator +=(BigInteger bi2){*this = *this + bi2;return *this;}BigInteger BigInteger::operator /(BigInteger bi2){BigInteger bi1(*this);BigInteger quotient;BigInteger remainder;int lastPos = maxLength - 1;bool divisorNeg = false, dividendNeg = false;if ((bi1.data[lastPos] & 0x80000000) != 0)     // bi1 negative{bi1 = -bi1;dividendNeg = true;}if ((bi2.data[lastPos] & 0x80000000) != 0)     // bi2 negative{bi2 = -bi2;divisorNeg = true;}if (bi1 < bi2){return quotient;}else{if (bi2.dataLength == 1)singleByteDivide(bi1, bi2, quotient, remainder);elsemultiByteDivide(bi1, bi2, quotient, remainder);if (dividendNeg != divisorNeg)return -quotient;return quotient;}}BigInteger BigInteger::operator -=(BigInteger bi2){*this = *this - bi2;return *this;}BigInteger BigInteger::operator -(BigInteger bi2)   //减法的重载{BigInteger bi1(*this);BigInteger result;int lastPos = maxLength - 1;bool bi1Neg = false, bi2Neg = false;if ((this->data[lastPos] & 0x80000000) != 0)     // bi1 negative    bi1Neg = true; if ((bi2.data[lastPos] & 0x80000000) != 0)     // bi1 negativebi2Neg = true;if(bi1Neg == false && bi2Neg == false)   //bi1,bi2都为正数{if(bi1 < bi2)    { result = -(bi2 - bi1); return result;    }result.dataLength = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;__int64 carryIn = 0;for (int i = 0; i < result.dataLength; i++)   //从低位开始减{__int64 diff;diff = (__int64)bi1.data[i] - (__int64)bi2.data[i] - carryIn;result.data[i] = (unsigned int)(diff & 0xFFFFFFFF);if (diff < 0)carryIn = 1;elsecarryIn = 0;}if (carryIn != 0){for (int i = result.dataLength; i < maxLength; i++)result.data[i] = 0xFFFFFFFF;result.dataLength = maxLength;}// fixed in v1.03 to give correct datalength for a - (-b)while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)result.dataLength--;// overflow checkif ((bi1.data[lastPos] & 0x80000000) != (bi2.data[lastPos] & 0x80000000) &&(result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000)){assert(false);}return result;}if(bi1Neg == true && bi2Neg == false)    //bi1负,bi2正{result = -(-bi1 + bi2);return result;}if(bi1Neg == false && bi2Neg == true)   //bi1正,bi2负{result = bi1 + (-bi2);return result;}if(bi1Neg == true && bi2Neg == true)   //bi1,bi2皆为负{BigInteger bi3 = -bi1, bi4 = -bi2;if(bi3 > bi4){ result = -(bi3 - bi4); return result;}else{result = bi4 - bi3;return result;}}}string BigInteger::DecToHex(unsigned int value, string format)   //10进制数转换成16进制数,并用string表示{string HexStr;int a[100]; int i = 0; int m = 0;int mod = 0; char hex[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};while(value > 0) { mod = value % 16; a[i++] = mod; value = value/16; } for(i = i - 1; i >= 0; i--){ m=a[i];HexStr.push_back(hex[m]);} while (format == string("X8") && HexStr.size() < 8){HexStr = "0" + HexStr;}return HexStr;}string BigInteger::ToHexString()  //功能:将一个大数用16进制的string表示出来{string result = DecToHex(data[dataLength - 1], string("X"));for (int i = dataLength - 2; i >= 0; i--){result += DecToHex(data[i], string("X8"));}return result;}ostream& operator<<(ostream& output, BigInteger &obj)//以16进制输出数值{ //if ((obj.data[obj.dataLength-1] & 0x80000000) != 0)     // bi1 negativefor(int i = obj.dataLength - 1; i >= 0; i--)output << hex << obj.data[i];return output;}bool Miller_Robin(BigInteger &bi1)   //Miller_Robin算法{BigInteger one((__int64)1), two((__int64)2), sum, a, b, temp;int k = 0, len = primeLength / 2;temp = sum = bi1 - one;while((sum.data[0] & 0x00000001) == 0)   //只要sum不为奇数,sum就一直往右移{sum.dataLength = sum.shiftRight(sum.data, maxLength, 1);   //右移一位k++;}//sum即为要求的奇数,k即是要求的2的次数srand((unsigned)time(0));for(int i = 0; i < len; i++){a.data[i] =(unsigned int)rand ();if(a.data[i] != 0) a.dataLength = i + 1;}b = a.modPow(sum, bi1);  //b = a^m mod bi1if (b == one) return true;   for(int i = 0; i < k; i++){if(b == temp) return true;else b = b.modPow(two, bi1);  //b = b^2 mod bi1}    return false;}BigInteger GetPrime(){BigInteger one((__int64)1), two((__int64)2), result, zero;srand((unsigned)time(0));bool flag = false;   //flag=false表示猜测该数为素数,flag=true表示该数一定为合数//随机产生一个大整数for(int i = 0; i < primeLength; i++){result.data[i] =(unsigned int)rand ();if(result.data[i] != 0)result.dataLength = i + 1;}result.data[0] |= 0x00000001;   //保证这个整数为奇数while (!flag){for(int i = 0; i < 303; i++)   //先用一些素数对这个整数进行筛选{BigInteger prime((__int64)primesBelow2000[i]);if(result % prime == zero){flag = true;break;}}        if(!flag){ cout << "第一轮素性检验通过… … … …" << endl; cout << "正在进行Miller_Robin素性检验… … … …" << endl; if(Miller_Robin(result))   //进行1次Miller_Robin检验 return result;   //通过了就返回result else flag = true;   //表明result是合数,没有通过检验}if(flag)   //如果没有通过检验,就+2,继续检验result = result + two;cout << "检验没有通过,进行下一个数的检验,运行之中… … … …" << endl;cout << endl;flag = false;}}BigInteger extended_euclidean(BigInteger n, BigInteger m, BigInteger &x, BigInteger &y)   //扩展的欧几里德算法  {  BigInteger x1((__int64)1), x2, x3(n);      BigInteger y1, y2((__int64)1), y3(m); BigInteger zero;    while(x3 % y3 != zero)      {  BigInteger d = x3 / y3;  BigInteger t1, t2, t3;          t1 = x1 - d * y1;          t2 = x2 - d * y2;          t3 = x3 - d * y3;          x1 = y1; x2 = y2; x3 = y3;          y1 = t1; y2 = t2; y3 = t3;      }      x = y1; y = y2;      return y3;  } /*BigInteger extended_euclidean(BigInteger n,BigInteger m,BigInteger &x,BigInteger &y)  {  BigInteger zero, one((__int64)1);    if(m == zero) { x = one; y = zero; return n; }      BigInteger g = extended_euclidean(m, n%m, x, y);      BigInteger t = x - n / m * y;      x = y;      y = t;      return g;  }  */BigInteger Gcd(BigInteger &bi1, BigInteger &bi2){BigInteger x, y;BigInteger g = extended_euclidean(bi1, bi2, x, y);return g;}BigInteger MultipInverse(BigInteger &bi1, BigInteger &n)   //求乘法逆元{   BigInteger x, y;   extended_euclidean(bi1, n, x, y);   if ((x.data[maxLength-1] & 0x80000000) != 0)     // x negative   x = x + n;  // unsigned int i =  x.data[maxLength-1] & 0x80000000;  // cout << i << endl;   return x;}

main.cpp

#include "BigInteger.h"#include <iostream>using namespace std;int main ( ){string a1, b1,c1;cin >> a1;cin >> b1; BigInteger a(a1, 10),b(b1, 10); //以10进制输入        //事先声明一句,答案全部以16进制输出        //BigInteger c;//cout << a << endl;//c = MultipInverse(a, b);  //求乘法逆//c = Gcd(a, b);  //求a.b最大公约数//BigInteger c, one((__int64)1);//for(int i = 0; i < maxLength; i++)//c.data[i] = 0xffffffff;//for(int i = 0; i < 10; i++)//cout << hex << c.data[i] << endl;//cout << hex << c.data[1] << endl;//cout << hex << c.data[maxLength-1];//if ((c.data[maxLength-1] & 0x8000000) != 0)//cout << flag << endl;cout << GetPrime() << endl;  //产生大素数//c = MultipInverse(a, b);//a.dataLength = a.shiftRight(a.data, maxLength, 1);//cout << c1 << endl;//c1 = a.modPow(b, n);//的确是幂模运算//cout << c1 << endl;//cout << a << endl;//cout << b << endl;//c = a / b;//c1 = c.ToHexString();  //将c变成16进制的字符串//cout << c1 << endl;//cout << c << endl;//cout << b << endl;system ("pause");return 0;}


原创粉丝点击