大位数

来源:互联网 发布:淘宝团队分工 编辑:程序博客网 时间:2024/04/29 16:48

大位数问题:int的表示范围是 -2147483648~2147483647 。 当两个正数相加的结果大于2147483647时,将会造成越界,而得到负数的结果。同样两个大位数相乘,也会导致越界的危险。为此,处理大位数问题时,普通的做法将无法满足需求。

解决方法主要有两种:

  • 利用现有的大数库。如:GNU MP等。可参考维基百科上的介绍 - GNU多重精度运算库

  • 自己动手写。

大位数加法

思路:

按照小学时算算术题的方法,从最低位开始相加,有进位时先记录下来,在下一位做加法时,加上进位。

/*大位数加法作者:Zoo时间:2016年4月20日21:19:49*/#include <iostream>#include <string>using namespace std;/*num1 : 大位数1,用字符串存储high1 : 大位数的最高位序号(字符串长度-1)*/void multiadd(char * num1, int len1, char * num2, int len2);int main(){    char s[] = "991";    char d[] = "19";    multiadd(s, 2, d, 1);    return 0;}void multiadd(char * num1, int len1, char * num2, int len2){    int i = 0, j = 0;    int flag = 0; //进位标志    string tmp;    while (i <= len1 && j <= len2)    {        int val = (num1[len1 - i++] - '0' + num2[len2 - j++] - '0' + flag);        tmp.append(1, val % 10 + '0');        flag = val / 10;    }    if (i > len1)    {        while (j <= len2)        {            int val = num2[len2 - j++] + flag - '0';            tmp.append(1, val % 10 + '0');            flag = val / 10;        }    }    else if (j > len2)    {        while (i <= len1)        {            int val = num1[len1 - i++] + flag - '0';            tmp.append(1, val % 10 + '0');            flag = val / 10;        }    }    if (flag != 0)    {        tmp.append(1, flag + '0');    }    // 输出     cout << string(tmp.rbegin(), tmp.rend()) << endl;}

大位数乘法

思路:

同上。关于大位数乘法,还可以利用FFT(傅里叶变换)的原理来解决。

/*大位数加法作者:Zoo时间:2016年4月20日21:19:49*/#include <iostream>#include <string>using namespace std;string multi(char * num1, int high1, char * num2, int high2,int cnt);void stradd(string & res, const string & src);void result(char * num1, int high1, char * num2, int high2);int main(){    result("123", 2, "123", 2);    return 0;}string multi(char * num1, int high1, char * num2, int high2, int cnt){    string res;    res.append(cnt, 0 + '0');    int flag = 0; //进位标志    while (high1 >= 0)    {        int mul = (num1[high1--] - '0') * (num2[high2] - '0');        res.append(1, (mul % 10 + flag) % 10 + '0');        flag = (mul % 10 + flag) / 10 + mul / 10;    }    return res;    string s(res.rbegin(), res.rend());    cout << s <<endl;}void stradd(string & res, const string & src){    int len1 = res.length();    int len2 = src.length();    int i = 0, j = 0;    int flag = 0;    string tmp;    while (i < len1 && j < len2)    {        int val = (res[i++] - '0'+ src[j++] - '0' + flag );        tmp.append(1,val % 10 + '0');        flag = val / 10;    }    if (i==len1)    {        while (j < len2)        {            int val = src[j++] + flag - '0';            tmp.append(1, val%10+'0');            flag = val / 10;        }    }    else if (j == len2)    {        while (i < len1)        {            int val = src[i++] + flag - '0';            tmp.append(1, val % 10 + '0');            flag = val / 10;        }    }    if (flag != 0)    {        tmp.append(1, flag + '0');    }    res = tmp;    return ;}void result(char * num1, int high1, char * num2, int high2){    int i = 0;    string res;    while ( (high2 - i) >= 0)    {        string tmp = multi(num1, high1, num2, high2-i, i);        i++;        stradd(res, tmp);    }    // 输出结果    cout << string(rbegin(res), rend(res)) << endl;}

进阶

求10亿个64位整数的平均数

1 0