高精度加法与高精度减法

高精度算法是什么:

1.在C++中,int,long long int等存储方式只能计算十几位的整数运算,想要计算更多位时,就需要用到高精度算法。

2.高精度算法是处理大数字的数学计算方法。一般会将小数点后有几百几千位的数字或者有几千亿几百亿的大数字统称为高精度数。

高精度算法的思想:

  将这种大数字拆开,拆成一位一位的,这样可已输入位数很长的数,接下来将每一位取出,存入数组中 ,然后用一个数组去存储每个数字,最后再将数组进行相应的运算(加、减、乘、除、等)。

---------------------------------------------------------------------------------------------------------------------------------

一、高精度加法

高精度加法思路:

  用字符串输入两个数,再导入数组,然后每位相加,如果某位数字>10,则此为模10,下一位+1,最后用while循环去除前导0再输入即可。

高精度加法易错点:

1.倒叙输入,倒叙输出,但中间运算是正着的。

2.相加之后的进位处理。

问题描述:求A+B

算法核心:
c[i] += a[i] + b[i]

c[i+1] = c[i]/10;

c[i] = c[i]%10;

代码一:

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10000;

string s1, s2; //定义两个字符串变量s1,s2,用于输入要相加的两个数字。
int a[N]; //加数1
int b[N]; //加数2
int c[N]; //和

int main()
{
    cin >> s1 >> s2;
    int j = 1, k = 1;//a,b数组的下标都是从1开始的

    //倒叙输入
    for (int i = s1.size() - 1; i >= 0; i--)
    {
        a[j++] = s1[i] - '0';  
    }
    for (int i = s2.size() - 1; i >= 0; i--)
    {
        b[k++] = s2[i] - '0';
    }

    int ma = max(s1.size(), s2.size()); //记录最大长度
    int ans = 0;    //进位位数
    for (int i = 1; i <= ma; i++)
    {
        ans = ans + (a[i] + b[i]);
        c[i] = ans % 10;;
        ans = ans / 10;
    }
    if (ans) //判断最后是否要进位
    {
        c[++ma] = ans;
    }
    for (int i = ma; i >= 1; i--)
    {
        cout << c[i];
    }
    return 0;

}

步骤:

1.读入存放到string中

因为这样长的整数,读取肯定不能用普通整数类型来存放,必须要用字符数组活string字符串来存放。

string s1,s2;

cin>>s1>>s2;

2.逆序转存整型数组

声明3个整型数组如a[250],b[250],c[300];将s1,s2分别逆序转存在a和b中。

int len = s1.length();
for (int i = 0; i < len; i++)
{
    a[len - 1 - i] = s1[i] - '0';
}
len = s2.length();
for (int i = 0; i < len; i++)
{
    b[len - 1 - i] = s2[i] - '0';
}

(逆序注意:数组下标为i的元素对应的逆序后的数组下标为len-1-i   (因为数组下标从0开始))

3.逐位相加,并处理进位

将两个整型数组a、b中对应的元素相加,并将结果存到数组c中

//循环计算每一位相加
for (int i = 0; i < len; i++)
{
    //相加
    c[i] += a[i] + b[i];
    //处理进位
    if (c[i] >= 10)
    {
        c[i + 1] += c[i] / 10;
        c[i] %= 10;
    }
}

注意这里进位时的代码,如果c[i]这一位上的数字>=10,则要进位,进到i+1位上去。

4.判断进位是否导致len(数字位数)增加

两个1位的数字相加,结果可能不再是1位,因为进位可能导致位数的增加,如何判断呢?原来的后一位是len-1位,现在我们看一下len位是否有数字就可以了。

//判断是否进位到了c[len]位

if(c[len] > 0)

{

  len++;

}

5.逆序输出

上面判断len的目的,就是未来此处的使用,因为要逆序输出,要知道从len位开始,而因为上面对len进行了++操作(如果进位了的话),所以此处仍然可以用len-1。

//逆序输出

for(int i = len-1;i>=0;i--)

{

    cout << c[i];

}

将高精度加法封装位函数

所谓封装成函数,就是我们传入两个string类型的整数,函数返回计算结果。

其思路与上面类似,只是参与计算的两个数,是由参数传入的。

除此之外,还有两点比较特殊

1.清楚公共数组变量的值

因为计算过程中用到的数组a,b,c是全局变量,所以每次使用前要清0.这里用到的是memset函数,以下对此函数做一个说明,memset函数在啊C++中使用时,要引用头文件string.h或memory.h。

其参数共有3个,

第一个参数:要清除的内存起始位置,如果是数组,则数组名同时是指针,也是指向其第一个元素位置的,故传数组名;

第二个参数:要将其初始化成的值,一般情况下会将其初始化为0,所以此处往往是填写数字0的;

第三个参数:要初始化的字节个数,注意是字节个数,如果此数组类型是int,则先通过sizeof(int)取到其每个元素的字节数,再乘以元素数。

通过这3个参数,函数就知道从哪里开始,往后的多少个字节,全部初始化为什么值了。

例:memset(a,0,sizeof(int)*MAXLEN);   //a是数组名,提前定义了#define MAXLEN 250,所以MAXLEN为数组长度

2.处理返回值

计算结果是函数返回的,而不是直接输出的,所以要将原本输出的值放到变量中。

这里我们声明了一个string类型的变量,然后将原本要输出的东西,存给他。

既然最后放到字符串中,那么原本c数组的元素要先转成字符型,才能存进去,所以有一个c[i]+'0'的操作。

//逆序转存成string

string ans;

for(int i = len -1 ; i>=0 ; i--)

{

  ans += c[i] + '0';

}

return ans;

---------------------------------------------------------------------------------------------------------------------------------

二、高精度减法

高精度减法是指两个大整数相减的操作。

其思路与高精度加法类似,只不过多了判断长度和前导0的去除操作。

步骤:

1.获取输入,并判断大小

对于字符串的大小判断,其实是判断字符串中字符的ascii编码,长的肯定大,长度相同,则ascii编码大的肯定大。

//读入两个字符串形式的整数
cin >> s1 >> s2;    //这里输入的s1可以小于s2,反正后面可以交换
//判断s1与s2的长度,长的肯定大,使得s1中存大的,s2中存小的
//若两者长度相等,则首字符ascii码大的,肯定大
if (s1.length < s2.length || (s1.length == s2.gth) && s1 < s2)
{
    swap(s1, s2);    //要是s1的数字小于s2,就交换s1,s2
    //因为s1长度小,所以结果一定是负数,所以直接输出符号
    cout << "-";
}

如果被减数<减数,则交换位置,并输出负号,为的是用大的数减去小的数。

2.逆序转存

这个代码与高精度加法无异

//将string类型逆序存放到整型数字中
int len = s1.length();
for (int i = 0; i < len; i++)
{
    a[len - 1 - i] = s1[i] - '0';
}
len = s2.length();
for (int i = 0; i < len; i++)
{
    b[len - 1 - i] = s2[i] - '0';
}
len = s1.length();

3.诸位计算,并处理借位

在加法时有进位处理,在减法时,自然就有借位处理了。

//循环计算每一位相减
for (int i = 0; i < len; i++)
{
    //判断借位处理
    if (a[i] < b[i])
    {
        a[i + 1]--;
        a[i] += 10;
    }
    c[i] = a[i] - b[i];
}

在进位时,进到的是结果位。在借位时,借的是被减数的位,所以要注意区别。

4.删除多余前导0

因为是减法,所以有可能减完后,某些位上可能会是0,如果这个位的前面没有1,则这个0是没有意义的,所以要将其删除。

//删除多余的前导0
while (c[len - 1] == 0 && len > 1)
{
    len--;
}

这个判断中,有一个len>1的处理,是未来保证至少留1位,即使这一位是0。

5.逆序输出结果

//逆序输出

for(int i = len-1;i>=0;i--)

{

        cout<<c[i];

}

代码:

#include <iostream>
#define MAXLEN 250
#define RMAXLEN 300
using namespace std;
string s1, s2;
int a[MAXLEN], b[MAXLEN], c[RMAXLEN];
int main()
{
    //读入两个字符串形式的整数
    cin >> s1 >> s2;
    //判断s1与s2的长度,长的肯定大,使得s1中存大的,s2中存小的
    //若两者长度相等,则首字符ascii码大的肯定大
    if (s1.length() < s2.length() || (s1.length() == s2.length() && s1 < s2))
    {
        swap(s1, s2);
        cout << "-";
    }
    //将string类型,逆序存放到整型数字中
    int len = s1.length();
    for (int i = 0; i < len; i++)
    {
        a[len - 1 - i] = s1[i] - '0';
    }
    len = s2.length();
    for (int i = 0; i < len; i++)
    {
        b[len - 1 - i] = s2[i] - '0';
    }
    len = s1.length();
    //循环计算每一位相减
    for (int i = 0; i < len; i++)
    {
        //判断借位处理
        if (a[i] < b[i])
        {
            a[i + 1]--;
            a[i] += 10;
        }
        c[i] = a[i] - b[i];
    }
    //删除多余的前导0
    while (c[len - 1] == 0 && len > 1)
    {
        len--;
    }
    //逆序输出
    for (int i = len - 1; i >= 0; i--)
    {
        cout << c[i];
    }
    return 0;
}

将高精度减法封装成函数的过程与高精度加法类似。

---------------------------------------------------------------------------------------------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值