大数四则运算的简单算法

大数相加

题目:任意两个数相加,计算结果

还有种特殊情况  这个题目中的两个数可能为正,可能为负

第一种情况,为正

思路:
1.将字符串倒序并转化为数字
2.逐位相加,并存入数组s[i]
3.对数组进行进制换算(这里有个需要特别注意的是 换算到最后,要考虑最后一位进制k值是否为零)
4.将数组反序输出

所用代码如下

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define Max 100000
int main()
{
    char str1[Max+10],str2[Max+10];
    while( cin>>str1>>str2)
    {
        int a[Max+10]={0},b[Max+10]={0},s[Max*2+10]={0},len1,len2,len;
        len1=strlen(str1);
        len2=strlen(str2);
        len=len1>len2?len1:len2;
        int x=0;
        //将字符串倒序并转化为数字
        for(int i=len1-1;i>=0;i--)
            a[x++]=str1[i]-'0';
        x=0;
        for(int i=len2-1;i>=0;i--)
            b[x++]=str2[i]-'0';
        int k=0;
        //逐位相加,并存入数组s[i]
       // 对数组进行进制换算
        for(int i=0;i<len;i++)
        {
            s[i]=(a[i]+b[i]+k)%10;
            k=(a[i]+b[i]+k)/10;
        }
        if(k!=0)
            printf("%d",k);
        int i;
        //将数组反序输出
        for(i=len-1;i>=0;i--)
        {
            if(s[i]!=0)
                break;
        }
        for(;i>=0;i--)
        {
            printf("%d",s[i]);
        }
        printf("\n");
    }
    return 0;
}

第二种情况   可能为负

思路

1.同上,先倒序输出,并转化为数字

2.判断该数是否为负数,若为负,则对数组内的每一个数字赋一个负号

3.逐位相加

4.判断数组s[i]的最后一位是否为负,分情况讨论,若为负,则输出一个负号

5.倒序输出,并且对s[i]加绝对值

所需代码如下:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
char aa[10010],bb[10010];
int a[10010],b[10010],c[10010];
int lena,lenb,len;
int main()
{
    while(~scanf("%s%s",aa,bb))
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        int x=0;
        lena=strlen(aa),lenb=strlen(bb);
//反序输出
        for(int i=lena-1; i>0; i--)
            a[x++]=aa[i]-'0';
//判断是否为负
        if(aa[0]=='-')
        {
            lena--;
            for(int i=0; i<lena; i++)
                a[i]=-a[i];
        }
        else  a[lena-1]=aa[0]-'0';
        x=0;
        for(int i=lenb-1; i>0; i--)
            b[x++]=bb[i]-'0';
        if(bb[0]=='-')
        {
            lenb--;
            for(int i=0; i<lenb; i++)
                b[i]=-b[i];
        }
        else b[lenb-1]=bb[0]-'0';
        int k=0;
        len=lena>lenb?lena:lenb;
//逐位相加
        for(int i=0; i<len; i++)
        {
            c[i]=(a[i]+b[i]+k)%10;
            k=(a[i]+b[i]+k)/10;
        }
        if(k)
            c[len++]=k;
        while(len>1&&c[len-1]==0) len--;
        int flag=1;
//判断是否为负数
        if(c[len-1]>=0)
        {
            for(int i=0; i<len; i++)
            {
                while(c[i]<0)
                {
                    c[i+1]--;
                    c[i]+=10;
                }
            }
        }
        if(c[len-1]<0)
        {
            flag=0;
            for(int i=0; i<len; i++)
            {
                while(c[i]>0)
                {
                    c[i+1]++;
                    c[i]-=10;
                }
            }
        }
        if(!flag) printf("-");
//倒序输出,并且加上绝对值
        while(len>1&&c[len-1]==0) len--;
        for(int i=len-1; i>=0; i--)
            printf("%d",abs(c[i]));
        printf("\n");
    }
}

大数相乘

题目:  任意两个数相乘,计算其结果

题目分析:该题主要注意结果的范围,简单的数字相乘,一般的代码程序可以运算,但大数的运算可能就会出现结果为负数,或者结果比所成积要小。所以要使用字符串的形式来进行运算,储存结果。

思路:

1.先将字符串倒序并转换为数字

2.逐位相乘,并存入一个数组s[i+j]中

3.处理进位,并消去多余的0

4.转换并把数组s[i]反转输出

所用代码如下:

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
#define Max 10000
int main()
{
    char str1[Max],str2[Max];
    int len1,len2;
    while(cin>>str1>>str2)
    {
    int a[Max+10]={0},b[Max+10]={0},s[2*Max+10]={0};
    len1=strlen(str1);
    len2=strlen(str2);
    int x=0;
    //将字符串反转过来,转化为数字
    for(int i=len1-1;i>=0;i--)
    {
        a[x]=str1[i]-'0';
        x++;
    }
    x=0;
     for(int i=len2-1;i>=0;i--)
    {
        b[x]=str2[i]-'0';
        x++;
    }
    //对两组字符串中的数逐位相乘,存于s[i+j]
    for(int i=0;i<len1;i++)
    {
        for(int j=0;j<len2;j++)
        {
            s[i+j]+=(a[i]*b[j]);
        }
    }
    //得到的结果进行进位制处理
    for(int j=0;j<Max*2;j++)
    {
        if(s[j]>=10)
        {
            s[j+1]+=s[j]/10;
            s[j]%=10;
        }
    }
    int i;
     //除去多余的0
  for(i=Max*2-1;i>=0;i--)
  {
      if(s[i]!=0)
        break;
  }
    //反转数组并输出结果
    for(;i>=0;i--)
    {
        printf("%d",s[i]);
    }
    printf("\n");
    }
    return 0;
}


这是小编第一次编写博客,因为小编是刚学没多久,里面的代码也是比较浅显易懂的,以后小编我会努力提升自我的水平的。。。。

大数减法

题目:任意两个数相减,求其结果

思路:

1.

2.

3.

4.

#include<stdio.h>
#include<string.h>
#define MAX 1000//大数的最大位数

int main()
{
    int sum[MAX]= {0}; //存放计算的结果,低位在前,高位在后,即sum[0]是低位
    char a[]="987654321987654321";//第一个大数
    char b[]="123456789123456789";//第二个大数
    int i,j,len,blag;
    char *temp_a=a,*temp_b=b,*temp;
    int n2[MAX]= {0};
    int a1=strlen(a);//计算数组num1的长度,即大数的位数
    int a2=strlen(b);//计算数组num2的长度,即大数的位数

    //在进行减法之前要进行一些预处理
    blag=0;//为0表示结果是正整数,为1表示结果是负整数
    if(a1<a2)//如果被减数位数小于减数
    {
        blag=1;//标记结果为负数
        //交换两个数,便于计算
        temp=temp_a;
        temp_a=temp_b;
        temp_b=temp;
        len=a1;
        a1=a2;
        a2=len;
    }
    else if(a1==a2)//如果被减数的位数等于减数的位数
    {
    //判断哪个数大
        for(i=0; i<a1; i++)
        {
            if(a[i]==b[i])
                continue;
            if(a[i]>b[i])
            {
                blag=0;//标记结果为正数
                break;
            }
            else
            {
                blag=1;//标记结果为负数
                //交换两个数,便于计算
                temp=temp_a;
                temp_a=temp_b;
                temp_b=temp;
                break;
            }
        }
    }
    len=a1>a2?a1:a2;//获取较大的位数

    //将num1字符数组的数字转换为整型数且逆向保存在整型数组sum中,即低位在前,高位在后
    for(i=a1-1,j=0; i>=0; i--,j++)
        sum[j]=a[i]-48;

    //转换第二个数
    for(i=a2-1,j=0; i>=0; i--,j++)
        n2[j]=b[i]-48;

    //将两个大数相减
    for(i=0; i<=len; i++)
    {
        sum[i]=sum[i]-n2[i];//两个数从低位开始相减
        if(sum[i]<0)//判断是否有借位
        {
            //借位
            sum[i]+=10;
            sum[i+1]--;
        }
    }

    //计算结果长度
    for(i=a1-1; i>=0&&sum[i]==0; i--)
        len=i+1;
    if(blag==1)
    {
        sum[len]=-1;//在高位添加一个-1表示负数
        len++;
    }
    //输出结果
    printf("%s\n-\n%s\n=\n",a,b);
    if(sum[i=len-1]<0)//根据高位是否是-1判断是否是负数
    {
        printf("-");//输出负号
        i--;
    }
    for(; i>=0; i--)
        printf("%d",sum[i]);
    printf("\n");
    return 0;
}

大数相除

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

以7546除以23为例:

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

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

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

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

下面是C语言的两个正大数相除的参考代码,计算结果中没有小数:

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
#define MAX 1000
/*
12   函数SubStract功能:
13   用长度为len1的大整数p1减去长度为len2的大整数p2
14   结果存在p1中,返回值代表结果的长度
15   不够减:返回-1 , 正好够:返回0
16 */
int SubStract(int *p1, int len1, int *p2, int len2)
{
    int i;
    if(len1 < len2)
        return -1;
    if(len1 == len2 )
    {
        // 判断p1 > p2
        for(i = len1-1; i >= 0; i--)
        {
            if(p1[i] > p2[i])   // 若大,则满足条件,可做减法
                break;
            else if(p1[i] < p2[i]) // 否则返回-1
                return -1;
        }
    }
    for(i = 0; i <= len1-1; i++)  // 从低位开始做减法
    {
        p1[i] -= p2[i];         // 相减
        if(p1[i] < 0)           // 若是否需要借位
        {
            // 借位
            p1[i] += 10;
            p1[i+1]--;
        }
    }
    for(i = len1-1; i >= 0; i--)  // 查找结果的最高位
    {
        if( p1[i] )             //最高位第一个不为0
            return (i+1);       //得到位数并返回
    }
    return 0;                   //两数相等的时候返回0
}


/*
 51   大数除法---结果不包括小数点
 52   num1 被除数
 53   num2 除数
 54   sum  商,存放计算的结果,即:num1/num2=sum
 55   返回数组sum的有效长度,即商的位数
 56 */
int Division(char num1[], char num2[], char sum[])
{
    int k, i, j;
    int len1, len2, len=0;     //大数位数
    int dValue;                //两大数相差位数
    int nTemp;                 //Subtract函数返回值
    int num_a[MAX] = {0};      //被除数
    int num_b[MAX] = {0};      //除数
    int num_c[MAX] = {0};      //商

    len1 = strlen(num1);       //获得大数的位数
    len2 = strlen(num2);

    //将数字字符转换成整型数,且翻转保存在整型数组中
    for( j = 0, i = len1-1; i >= 0; j++, i-- )
        num_a[j] = num1[i] - '0';
    for( j = 0, i = len2-1; i >= 0; j++, i-- )
        num_b[j] = num2[i] - '0';

    if( len1 < len2 )          //如果被除数小于除数,直接返回-1,表示结果为0
    {
        return -1;
    }
    dValue = len1 - len2;      //相差位数
    for (i = len1-1; i >= 0; i--)    //将除数扩大,使得除数和被除数位数相等
    {
        if (i >= dValue)
            num_b[i] = num_b[i-dValue];
        else                         //低位置0
            num_b[i] = 0;
    }
    len2 = len1;
    for(j = 0; j <= dValue; j++ )    //重复调用,同时记录减成功的次数,即为商
    {
        while((nTemp = SubStract(num_a, len1, num_b+j, len2-j)) >= 0)
        {
            len1 = nTemp;            //结果长度
            num_c[dValue-j]++;       //每成功减一次,将商的相应位加1
        }
    }
    // 计算商的位数,并将商放在sum字符数组中
    for(i = MAX-1; num_c[i] == 0 && i >= 0; i-- );  //跳过高位0,获取商的位数
    if(i >= 0)
        len = i + 1; // 保存位数
    for(j = 0; i >= 0; i--, j++)     // 将结果复制到sum数组中
        sum[j] = num_c[i] + '0';
    sum[j] = '\0';   // sum字符数组结尾置0
    return len;      // 返回商的位数
}

int main()
{
    int i;
    int len;                // 商的位数
    char num1[MAX] = "1234567899876543210";   // 第一个大数
    char num2[MAX] = "20160415123025";              // 第二个大数
    char sum[MAX] = {0};    // 计算结果

    //scanf("%s", num1);      //以字符串形式读入大数
    //scanf("%s", num2);

    len = Division(num1, num2, sum);

    //输出结果
    printf("%s\n  ÷\n%s\n  =\n", num1, num2);
    if( len>=0 )
    {
        for(i = 0; i < len; i++ )
            printf("%c", sum[i]);
    }
    else
    {
        printf("0");
    }
    printf("\n");

    return 0;
}



















猜你喜欢

转载自blog.csdn.net/qq_42133828/article/details/82492608
今日推荐