BUAA(2021春)超长正整数的减法(高精度减法)+其他三种高精度运算

这篇博客主要介绍了如何实现超长正整数的高精度减法,并提供了加法、乘法和除法的算法实现。内容包括字符串与数字的转换、模拟减法过程、处理前导零以及三种额外的高精度运算。通过示例代码详细解释了每种运算的过程,适合初学者掌握高精度计算技巧。

看前须知

要点介绍和简要声明.

第一次上机题汇总

扩展字符A——strchr的灵活使用.

表达式求值.

小数形式与科学计数法转换(简)——分类讨论一定要有逻辑.

超长正整数的减法(高精度减法)+其他三种高精度运算.

全排列数的生成——DFS(深度优先遍历)+回溯 秒杀本题.

题目内容

问题描述

编写程序实现两个超长正整数(每个最长80位数字)的减法运算。

输入形式

从键盘读入两个整数,要考虑输入高位可能为0的情况(如00083)。

  1. 第一行是超长正整数A;
  2. 第二行是超长正整数B;

输出形式

输出只有一行,是长整数A减去长整数B的运算结果,从高到低依次输出各位数字。要求:若结果为0,则只输出一个0;否则输出的结果的最高位不能为0,并且各位数字紧密输出。

样例

输入

234098
134098703578230056

输出

-134098703577995958

样例说明

进行两个正整数减法运算, 234098 -134098703578230056 = -134098703577995958。

题解

易错点和难点

模拟高精度减法,注意字符串和数字之间的转换,还有要注意减法可以会造成多余的前导零,一定要删除

参考博文(所有高精度及其详解)

高精度.

参考代码

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<ctype.h>
#define M 100
void front0(char *p0);   //删去前导零 
char s[M],ss[M];
int a[M],b[M];
int len,i; 
int main()
{
    scanf("%s%s",s,ss);
    front0(s);
    front0(ss);
    int l1 = strlen(s);  
    int l2 = strlen(ss);
    int flag = 0;         
    memset(a,0,sizeof(a));  
    memset(b,0,sizeof(b));  
    if ( l1 < l2 || (strcmp(s,ss) < 0 && l1 == l2) )   //找到较大的那个字符串   
    {                                          
        flag = 1; 
        for (i = l2 - 1 ; i >= 0 ; i--)    
            a[l2 - i - 1] = ss[i] - '0';    //转化为数字 
        for (i = l1 - 1 ; i >= 0 ; i--)		
            b[l1 - i - 1] = s[i] - '0';		//转化为数字
    }
    else
    {
        for (i = l1 - 1 ; i >= 0 ; i--)  	//转化为数字
            a[l1 - i - 1] = s[i] - '0';
        for (i = l2 - 1 ; i >= 0 ; i--)
            b[l2 - i - 1] = ss[i] - '0';	//转化为数字
    }
    if (l1 > l2)
	{
		len = l1;
	}                
    else
	{
		len = l2;
	}  
    for (i = 0 ; i < len ; i++)
    {
        a[i] = a[i] - b[i];     //模拟减法 
        if (a[i] < 0)         
        {
            a[i+1]-=1;          //借位 
            a[i]+=10;          
        }
    }

    while (a[len - 1] == 0 && len>1)
	{
		len--;   //删去减法中出现的前导零 
	} 
    if (flag == 1) 
	{
		printf("-");
	}     
    for (i = len - 1 ;i >= 0 ;i--)
	{
		printf("%d",a[i]);
	}  
       
    printf("\n"); 
    
    return 0;
}
void front0(char *p0){ //删去前导零 
	char tmp[M];
	int i;
	for(i=0;i<strlen(p0);i++){
		if(*(p0+i)!='0') break;
	}
	strcpy(tmp,p0+i);         
	strcpy(p0,tmp);
}

其他三种高精度运算

高进度加法

#include<stdio.h>
#include<string.h>
char s[10100],ss[10100];
int a[10100],b[10100];
int len;

void jia()     //自定义函数"jia"(名字low了一点(好像不是一点,但容易理解不是吗)) 
{
	int l1 = strlen(s);     //"strlen"是一个计算字符串长度的函数 
	int l2 = strlen(ss);    //将输入的两个字符串的长度赋值给l1,l2
	if (l1 > l2) 
		len = l1;      //将len赋值为l1,l2中大的那个 
	else 
		len = l2;
//		for (int i = 0 ; i <= len ; i++)  //清零(这里for循环和下面三句memset都为将字符串清零 ) 
//			a[i] = b[i] = c[i] = 0;
	memset(a,0,sizeof(a));    //清零too(只能清零,不能干别的) 
	memset(b,0,sizeof(b));    //这是清零函数(字符串) 
	                                       //两个for循环是将输入的两个字符串倒过来
	for (int i = l1 - 1 ; i >= 0 ; i--)    //再将字符串里的字符转换为数字赋值给a,b整型数组 
		a[l1 - i - 1] = s[i] - '0';        //但为什么大数要用字符串存呢?
	for (int i = l2 - 1 ; i >= 0 ; i--)    //因为大数太大,用任何整型变量都存不下 
		b[l2 - i - 1] = ss[i] - '0';       //为什么要把字符串倒过来赋值呢? 
	                                //因为大数与大数是一位一位运算的,还要涉及进位等 
	for (int i = 0 ; i < len ; i++)
	{
		a[i] = a[i] + b[i];    //运算 
		a[i+1]+= a[i] / 10;    //如有进位,在后一位上加上 
		a[i] = a[i] % 10;      //原来那一位减掉进位了的 
	}
	if (a[len] != 0) len++;    //如果有进位就多显示一位(这句话很重要) 

	while (a[len - 1] == 0 && len>1) len--;		//我叫它while去零法
		
	for (int i = len - 1 ;i >= 0 ;i--)  //输出结果 
		printf("%d",a[i]);
	printf("\n");
}                              //高精度加法你懂了吗?

int main()
{
	scanf("%s%s",s,ss);
	
		jia();     //引用高精度加法函数
	
	return 0;
}

高进度乘法

void cheng_gao()     //高是指高精度乘高精度 
{
	len = strlen(s);
	lenn = strlen(ss);
	memset(a,0,sizeof(a));   //清零数组
	memset(b,0,sizeof(b));
	memset(c,0,sizeof(c));	
	for (int i = 0 ; i < len ; i++)
		a[len - i - 1] = s[i] - '0';    //将字符串转化为数组 
	for (int i = 0 ; i < lenn ; i++)
		b[lenn - i - 1] = ss[i] - '0';
		
	memset(c,0,sizeof(c));   //清零 
	for (int i = 0 ; i < len ; i++)
		for (int j = 0 ; j < lenn ; j++)
			c[i + j] += a[i] * b[j];       //运算(这个就有一点复杂了) 
		
	int l = len + lenn - 1;    //l是结果的最高位数 
	for (int i = 0 ; i < l ;i++)
	{
		c[i + 1] += c[i] / 10;    //保证每一位的数都只有一位,并进位 
		c[i] %= 10;
	}
	if (c[l] > 0) l++;     //保证最高位数是对的 
	while (c[l - 1] >= 10)
	{
		c[l] = c[l - 1] / 10;
		c[l - 1] %= 10;
		l++;
	}
	while (c[l - 1] == 0 && l > 1) 
		l--;    //while去零法 
	for (int i = l - 1; i >= 0 ; i--)    //输出结果 
		printf("%d",c[i]);
	printf("\n");     //换行 
}                               //高精度乘法(高)你懂了吗



int main()
{
	int t;

	
	    scanf("%s%s",s,ss);
        cheng_gao();    //引用高精度乘法函数
	
	return 0;
}

高进度除法

#include<stdio.h>
#include<string.h>
char s[1000000];
int a[1000000],b[1000000];
int len,lenb;
int d,yu;
	

void chu_di()       //高精除低精 
{
	int yu=0;
	memset(a,0,sizeof(a));    //清空数组a 
	memset(b,0,sizeof(b));
	len=strlen(s);            //s的长度 
	for(int i=0;i<=len-1;i++)
		a[i+1]=s[i]-'0';
	for(int ii=1;ii<=len;ii++)
	{
		b[ii]=(yu*10+a[ii])/d;
		yu=(yu*10+a[ii])%d;
	}
	int lenb=1;
	while(b[lenb]==0&&lenb<len)
		lenb++;
	printf("结果:\n");
	printf("%s ÷ %d = ",s,d);
	for(int j=lenb;j<=len;j++)
		printf("%d",b[j]);
	if(yu!=0)
		printf("......%d",yu);
	printf("\n");       
}                               //高精度除法(高)你懂了吗

int main()
{

	while (scanf("%s%d",s,&d)!=EOF)
	{
        chu_di();  
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值