大数四则运算之大数加法和减法

前言

    众所周知,在计算机中数字的表示范围是有限的,比如我们熟知的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;   // 返回结果的位数 
}

在实际运算中,可以根据不同情况,进行判定。

猜你喜欢

转载自blog.csdn.net/qq_42057046/article/details/88671512