大位数

大位数问题: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位整数的平均数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值