前言
众所周知,在计算机中数字的表示范围是有限的,比如我们熟知的int,float,double等数据类型所能表示的范围都是有限的,如果我们要对位数达到几十位,几百位,甚至是上千位的大整数进行计算,这些数据类型显然不能满足我们的要求,因此我们应该如何实现大数的计算呢。
原理
首先我们先讨论大数的加法,我们都知道两个数相加,就是从低位开始相加,满十进一。因此,我们在进行大数运算时为什么不能使用算法模拟进位呢。
首先我们定义两个大整数,n1,n2。分别使用字符保存。
定义sum为量大数相加的结果(即sum=n1+n2)
为了进行大数加法的按位计算,我们还需要得出两数的长度(使用length函数即可)
之后的计算将在代码中给出。
注意:此处所讨论的大数加法是在两数都为正数的基础上,如果两数有负数则需要另行讨论(个人想法是进行条件判定,如果两数一正一负,相当于做减法运算。如果两数都为负,只需先去掉符号进行计算,结果为负即可。)。
下面给出了大数加法的函数
int Add(char a1[], char a2[], int sum[])
{
int i, j, len;
int n2[MAX] = {0};
int len1 = strlen (a1); // 计算数组a1的长度
int len2 = strlen (a2); // 计算数组a2的长度
len = len1>len2 ? len1 : len2; // 获取较大的位数,a=(条件)?c:b 表示的意思是当条件成立时a=c。不成立时,a=b
//将a1转换为整型数字逆向保存在整型数组sum中,即数组sum中位阶由低到高
for (i = len1-1, j = 0; i >= 0; i--, j++)
{
sum[j] = a1[i] - '0';//字符型数据转换为整数时要烤考虑其ASCII值
}
// 转换第二个数
for (i = len2-1, j = 0; i >= 0; i--, j++)
{
n2[j] = a2[i] - '0';
}
// 将两个大数相加
for (i = 0; i <= len; i++)
{
sum[i] += n2[i]; // 两个数从低位开始相加
if (sum[i] > 9) // 判断是否有进位
{ // 如果进位将此时的数(最大为18即9+9)减10取零,并向高位进1.
sum[i] -= 10;
sum[i+1]++;//进位
}
}
if(sum[len] != 0) // 判断最高位是否有进位
{
len++;
}
return len; // 返回和的位数
}
大数减法
大数减法和大数加法类似,区别在于做加法运算时需要进行进位运算,而减法需要进行借位运算。
在进行减法运算时也是从低位开始的,如同加法一样需要先判定减数和被减数哪一位数长。如果被减数位数长则作正常减法;如果减数位数长,则用减数减去被减数(减数-被减数),结果加上负号;当两数位数长度相等时,比较哪个数字大,再根据情况运算;具体情况将在代码中给出;
int Sub(char a1[], char a2[], int sum[])
{
int i, j, len, blag;
char *temp;
int n2[MAX] = {0};
int len1 = strlen(a1); // 计算数组a1的长度
int len2 = strlen(a2); // 计算数组a2的长度
// 在进行减法之前要进行一些预处理
blag = 0; // 用于结果判定当blag为0结果为正,为1表时结果为负
if(len1 ==len2) // 如果被减数的位数等于减数的位数
{
// 判断哪个数大
for(i = 0; i < len1; i++)
{
if(a1[i] == a2[i])
{
continue;
}
if(a1[i] > a2[i])
{
blag = 0; // 标记结果为正数
break;
}
else
{
blag = 1; // 标记结果为负数
// 交换两个数,便于计算
temp = a1;
a1 = a2;
a2 = temp;
break;
}
}
}
else if(len1 < len2) // 如果被减数位数小于减数
{
blag = 1; // 标记结果为负数
// 交换两个数,便于计算
temp = a1;
a1 = a2;
a2 = temp;
len = len1;
len1 = len2;
len2 = len;
}
len = len1>len2 ? len1 : len2; // 获取较大的位数
//将a1字符数组的数字转换为整型数且逆向保存在整型数组sum中,即低位在前,高位在后
for (i = len1-1, j = 0; i >= 0; i--, j++)
{
sum[j] = a1[i] - '0';
}
// 转换第二个数
for (i = len2-1, j = 0; i >= 0; i--, j++)
{
n2[j] = a2[i] - '0';
}
// 将两个大数相减
for (i = 0; i <= len; i++)
{
sum[i] = sum[i] - n2[i]; // 从低位开始相减
if (sum[i] < 0) // 判断是否有借位
{ // 借位
sum[i+1]--;
sum[i] += 10;
}
}
// 计算结果长度 ,找到结果的最高位再其前面加上负号
for (i = len1-1; i>=0 && sum[i] == 0; i--);
len = i+1;
if(blag==1)
{
sum[len] = -1; // 在高位添加一个-1表示负数
len++;
}
return len; // 返回结果的位数
}
在实际运算中,可以根据不同情况,进行判定。
扫描二维码关注公众号,回复:
6183827 查看本文章