大数的四则运算(加,减,乘,除)处理

简介: 大数的四则运算(加,减,乘,除)处理

一、大数相除


基本思路

大数除法是四则运算里面最难的一种。不同于一般的模拟,除法操作不是模仿手工除法,而是利用减法操作来实现的。其基本思想是反复做除法,看从被除数里面最多能减去多少个除数,商就是多少。逐个减显然太慢,要判断一次最多能减少多少个整数(除数)的10的n次方。


以7546除以23为例:

先用7546减去23的100倍,即减去2300,可以减3次,余下646,此时商就是300 (300=1003);

然后646减去23的10倍,即减去230,可以减2次,余下186,此时商就是320 (320=300+102);

然后186减去23,可以减8次,余下2,此时商就是328 (328=320+1*8);

因为2除以23的结果小于1,而我们又不用计算小数点位,所以不必再继续算下去了。


代码如下

#include <stdio.h>
#include <string.h>
#define MAXnumber 1000
int SubStract(int numdata1[], int num1size, int numdata2[], int num2size);
int main()
{
  char num1[MAXnumber] = {0};  //除数
  char num2[MAXnumber] = {0};  //被除数
  int numdata1[MAXnumber] = {0};
  int numdata2[MAXnumber] = {0};
  int result[MAXnumber] = {0};  //结果
  int num1size,num2size;
  int dvalue;
  int nTemp;
  int i,j,x;
  //输入被除数与除数
  scanf("%s",num1);
  num1size = strlen(num1);
  scanf("%s",num2);
  num2size = strlen(num2);
  //字符串倒序转化成数字,也就是个位数在0号位置
  x = 0;
  for(i = num1size - 1; i >= 0; i--){
  numdata1[x] = num1[i] - 48;
  x++;
  }
  x = 0;
  for(i = num2size - 1; i >= 0; i--){
  numdata2[x] = num2[i] - 48;
  x++;
  }
  //将除数填充到与被除数相同的位数,也就是向右平移一个差值dvalue的位置。numdata2[i] = numdata2[i - dvalue]; 
  //然后平移之后,其余数位填充为0.此时位数与被除数相同
  dvalue = num1size - num2size;
  for(i = num1size - 1; i >= 0; i--){
  if(i - dvalue >= 0){
    numdata2[i] = numdata2[i - dvalue];  //将除数扩大,使得除数和被除数位数相等
  }
  else{
    numdata2[i] = 0;  //其余填充为0
  }
  }
  num2size = num1size;    //更改被除数位数
  //此步为关键步骤,重复调用,同时记录减成功的次数,即为商
  //得到的商不可能大于差值,所以大范围循环是0-dvalue,目的是不断使对应的数位+1.
  //numdata2+i相当于除数向左移位,也就是去一个0;num2size - i表示被除数位数减一
  //由于除法运算是不断的相减,所以当被除数不够减时,最高位为0,此时记录其位数nTemp,再反复循环
  for(i = 0; i <= dvalue; i++){  
  while((nTemp = SubStract(numdata1, num1size, numdata2 + i, num2size - i)) >= 0 ){
    num1size = nTemp; //结果长度
    result[dvalue - i]++; //每成功减一次,将商的相应位加1
  }
  }
  //输出商,逆向输出
  printf("\n%s\n/\n%s\n=\n",num1,num2);
  for(i = dvalue; result[i] == 0; i--);
  for(; i >= 0; i--){
  printf("%d",result[i]);
  }
  //输出余数  
  printf("\n余数为");
  for(i = dvalue; numdata1[i] == 0; i--);
  for(; i >= 0; i--){
  printf("%d",numdata1[i]);
  }
  return 0;
}
int SubStract(int numdata1[], int num1size, int numdata2[], int num2size)
{
  int i;
  //判断能否满足减法运算
  if(num1size < num2size){  
  return -1;
  }
  if(num1size == num2size){
  for(i = num1size - 1; i >= 0; i--){
    if(numdata1[i] > numdata2[i]){
    break;
    }
    else if(numdata1[i] < numdata2[i]){
    return -1;
    }
  }
  }
  //不够减借位
  for(i = 0; i <= num1size - 1; i++){
  numdata1[i] -= numdata2[i];
  if(numdata1[i] < 0){
    numdata1[i] += 10;
    numdata1[i+1]--;
  }
  }
  //查找结果的最高位,返回的是此时被除数的位数,两数相等时返回0.
  for(i = num1size - 1; i >= 0; i--){
  if(numdata1[i]){
    return (i+1);
  }
  }
  return 0;
}


测试结果

image.png


二、大数相乘


基本思路

  1. 使用字符串对数据的输入
  2. 字符串倒序转换成数字
  3. 两个数组模仿乘法处理实现相乘,注意处理进位
  4. 消去多余的0
  5. 将结果翻转输出即为大数相乘的结果


代码如下

#include <stdio.h>
#include <string.h>
#define MAXnumber 1000
int main()
{
  char firstnum[MAXnumber] = {0};
  char secondnum[MAXnumber] = {0};
  int firstnumdata[MAXnumber] = {0};
  int secondnumdata[MAXnumber] = {0};
  int resultdata[MAXnumber] = {0};
  int firstsize,secondsize;
  int i,j,x;
  scanf("%s",firstnum); //输入第一个数据
  firstsize = strlen(firstnum); 
  scanf("%s",secondnum);  //输入第二个数据
  secondsize = strlen(secondnum);
  //字符串转换成数据
  x = 0;
  for(i = firstsize - 1; i >= 0; i--){  
  firstnumdata[x] = firstnum[i] - 48;
  x++;
  }
  x = 0;
  for(i = secondsize - 1; i >= 0; i--){
  secondnumdata[x] = secondnum[i] - 48;
  x++;
  }
  //大数相乘并处理好进位
  for(j = 0; j < secondsize; j++){
  for(i = 0; i < firstsize; i++){
    resultdata[i+j] += firstnumdata[i]*secondnumdata[j];
  }
  }
  for(i = 0; i < MAXnumber; i++){
  if(resultdata[i] >= 10){
    resultdata[i+1] += resultdata[i]/10;
    resultdata[i] = resultdata[i]%10;
  }
  }
  //翻转输出,并消除末尾多余的0
  printf("%s*%s=",firstnum,secondnum);
  for(i = MAXnumber - 1; resultdata[i] == 0; i--);
  for(; i >= 0; i--){
  printf("%d",resultdata[i]);
  }
  return 0;
}


测试结果

image.png


三、大数相减


基本思路

方法相识,只是要做正负数的判断处理,同时不够减时向高位借位。


代码如下

#include <stdio.h>
#include <string.h>
#define MAXnumber 1000
int main()
{
  char num1[MAXnumber] = {0};
  char num2[MAXnumber] = {0};
  int numdata1[MAXnumber] = {0};
  int numdata2[MAXnumber] = {0};
  int result[MAXnumber] = {0};
  int num1size,num2size;
  int i,j,x;
  int flag = 1; //默认是正整数
  scanf("%s",num1);
  num1size = strlen(num1);
  scanf("%s",num2);
  num2size = strlen(num2);
//字符串转换成数据
  x = 0;
  for(i = num1size - 1; i >= 0; i--){
  numdata1[x] = num1[i] - 48;
  x++;
  }
  x = 0;
  for(i = num2size - 1; i >= 0; i--){
  numdata2[x] = num2[i] - 48;
  x++;
  }
  //结果的正负号处理
  if(num1size < num2size){  //长度不匹配,负数
  flag = 0;
  }
  else if(num1size == num2size){  //从高位开始匹配每一位,若被减数较小,负数
  for(x = num1size - 1; x >= 0; x--){
    if(numdata1[x] == numdata2[x]){
    continue;
    }
    else if(numdata1[x] < numdata2[x]){
    flag = 0;
    break;
    }
  }
  }
  //减法处理,不够减向高位借位
  if(flag){
  for(i = 0; i < MAXnumber; i++){
    if(numdata1[i] < numdata2[i]){
    numdata1[i+1]--;
    result[i] = numdata1[i]+10-numdata2[i];
    }
    else{
    result[i] = numdata1[i]-numdata2[i];
    }
  } 
  }
  else{
  for(i = 0; i < MAXnumber; i++){
    if(numdata2[i] < numdata1[i]){
    numdata2[i+1]--;
    result[i] = numdata2[i]+10-numdata1[i];
    }
    else{
    result[i] = numdata2[i]-numdata1[i];
    }
  } 
  }
  //结果翻转输出
  printf("\n%s\n-\n%s\n=\n",num1,num2);
  if(flag == 0){
  printf("-");
  }
  for(i = MAXnumber - 1; result[i]==0; i--);
  for(; i >= 0; i--){
  printf("%d",result[i]);
  }
  return 0;
}


测试结果

image.png


四、大数相加


基本思路

同样是利用数组不断的进位,最后消0反转输出


代码如下

#include <stdio.h>
#include <string.h>
#define MAXnumber 1000
int main()
{
  char num1[MAXnumber] = {0};
  char num2[MAXnumber] = {0};
  int numdata1[MAXnumber] = {0};
  int numdata2[MAXnumber] = {0};
  int result[MAXnumber] = {0};
  int num1size,num2size;
  int i,j,x;
  scanf("%s",num1);
  num1size = strlen(num1);
  scanf("%s",num2);
  num2size = strlen(num2);
  x = 0;
  for(i = num1size - 1; i >= 0; i--){
  numdata1[x] = num1[i] - 48;
  x++;
  }
  x = 0;
  for(i = num2size - 1; i >= 0; i--){
  numdata2[x] = num2[i] - 48;
  x++;
  }
  for(i = 0; i < MAXnumber; i++){
  result[i] = numdata1[i] + numdata2[i];
  }
  for(i = 0; i < MAXnumber; i++){
  if(result[i] >= 10){
    result[i+1]++;
    result[i] = result[i] % 10;
  }
  }
  printf("\n%s\n+\n%s\n=\n",num1,num2);
  for(i = MAXnumber - 1; result[i]==0; i--);
  for(; i >= 0; i--){
  printf("%d",result[i]);
  }
  return 0;
}


测试结果

image.png

目录
相关文章
|
21天前
求一个整数的所有因数
【10月更文挑战第25天】求一个整数的所有因数。
14 5
|
6月前
|
存储 C语言
大数的加、减、乘、除、幂运算(C语言)
大数的加、减、乘、除、幂运算(C语言)
|
存储
A除于B(大数相除)
A除于B(大数相除)
70 0
|
算法
不使用+或-运算符,计算两数之和
不使用+或-运算符,计算两数之和
84 0
求实数的整数次幂(循环版)(高效)(位运算解题)
说明:参数 x 为底数,n 为指数。若参数正确,则函数值为 x 的 n 次幂。若参数不正确(当底数为 0 且指数为 0 或负数时无意义),则报告错误,函数值为0。// 这个位运算是大部分都不熟悉也不敢用的东西,但是确实是编程里面的一个非常重要的工具。请编写函数,用循环语句以最快的方法求任意实数的任意整数次幂。要求:不得调用 pow 函数,不得使用递归方法。指数 二进制 公式。
217 0
求实数的整数次幂(循环版)(高效)(位运算解题)
7-2 一元多项式的乘法与加法运算 (20 分)
7-2 一元多项式的乘法与加法运算 (20 分)
143 0
7-41 大数的乘法 (10 分)
7-41 大数的乘法 (10 分)
79 0
|
存储 算法
高精度加法,模拟大数的加法运算
在处理特别大的数相加特别大的数的时候,long long不能直接通过加法算出结果的时候,可以通过高精度算法处理这些数的相加具体·思路如下; 首先 1 . 这些数存到数组的时候该如何排列,是个位放在第一位还是最后一位放到第一位,由于数的相加的候常常出现进位,常在最后一位加上一个数,而加上数的话往往在数组最后一位加上数比较方便,所以我们把第个位放在数组第一位 2.其次在调用模拟大数相加的函数中,我们该如何处理同一位上数相加出现的进位呢,我们可以设置一个 t 存储数组上某位相加最后吧 t%10 ,就可以得到想要的数,同时在 t / 10 如果 t 会的得到 1 或者 0.
135 0
算法零基础——大数四则运算
算法零基础——大数四则运算
算法零基础——大数四则运算