• 大数,高精度计算---百位大数


    大数是算法语言中的数据类型无法表示的数,其位数超过最大数据类型所能表示的范围,所以,在处理大数问题时首先要考虑的是怎样存储大数,然后是在这种存储方式下其处理的实现方法。

    一般情况下大数的存储是采用字符数组来存储,即将大数当作一个字符串来存储,而对其处理是按其处理规则在数组中模拟实现。

    七 百位大数。

    百位大数...让人又爱又恨阿。  回想去年,初学c语言,实验就有这个。
    那时候折腾老久了。            刻苦铭心呀。
    写这篇博客,没其他意思,主要是为了回忆回忆,然后记录一下当初的代码,便于以后翻看。

    代码是大一上学期写的。可能比较水,大神们勿喷,纯属自己娱乐罢了。
     
    实验题目:

    此次实验要求利用数组实现两个百位大数(共有100位数字)的加、减、乘法的运算。
    实现下列三个函数的功能(以下函数应在fun.h中声明,在fun.c中实现)
      函数原型:

    /*实现两个大数的相加*/
       char* add(char* data, char* addend, char* result);

    /*实现两个大数的相减*/
       char* minus(char* data, char* sub, char* result);

    /*实现两个大数的相乘*/
       char* multiply(char* data, char* mult, char* result);

    实验内容:

    在给出的程序框架中完成实验题目。
    mylib.c包括此次实验的程序框架。
     (在给出的程序框架中补充设计并完成实验。)

    注:检验计算结果是否正确可利用提供的 test.exe 文件。
    在mylib.exe和test.exe文件中输入相同的种子则会产生相同的随机大数。可以用test.exe产生的结果和mylib.exe对照结果检验对错。

    请注意其中test.exe文件的输出格式和框架规定的输出格式有所不同。

    提示:

    字符型与整型转换

    1.可以模拟笔算加减乘的过程,用数组储存大数;
    2.可以用atoi和itoa函数;
    3.对于一位整数的整型转换为字符型:

    例:
    char c;
    int i = 9;
    c = i+’0’;
    printf(“%c”, c);



    main.c

    /* 姓名:****
       班级:软件三班
       学号:****
       功能:百位大数
       时间:2012.12.2  */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "fun.h"
    
    #define N 100
    
    /* 产生随机的大数  */
    void create(char* num, unsigned seed);  /*seed 为随机种子*/
    
    char result[2 * N] = {''};
    
    int main(void)
    {
        char num[N];//多出符号位
        char n[N];
    
        //设定随机种子
        unsigned int seed;
        printf("Please input a  rand seed:");
        scanf("%u", &seed);
        printf("
    The seed is %u
    ", seed);
      //产生随机大数
        create(num, seed);
        create(n, seed+1);
        printf("***********************************************
    ");
        printf("num: %s
     n : %s
    ", num, n);
    
        //调用加法
        add(num, n, result);
        printf("num + n = %s
    ", result);
    
        //调用减法
        minus(num, n, result);
        printf("num - n = %s
    ", result);
    
        //调用乘法
        multiply(num, n, result);
        printf("num * n = %s
    ", result);
    
        system("pause");
        return 0;
    }
    
    void create(char num[], unsigned seed)
    {
        int i = 0, x = 0;
        int times, flag = 1;
        srand(seed);
        times = rand() % (N - 2) + 1;//避免溢出
        if(rand() % 2)//随机生成负数
    {
            num[i] = '-';
            i++;
            if(times == 1)
                times++;
        }
        while(flag)//避免高位为零
        {
            x = rand() % 10;
            if(x != 0)
            {
                flag = 0;
            }
        }
        num[i] = x + '0';
        i++;
        for(; i < times; i++)
        {
            x = rand() % 10;
            num[i] = x + '0';
        }
        num[times] = '';
    }
    

    fun.h

    #ifndef FUN_H_INCLUDED
    #define FUN_H_INCLUDED
    
    //此方法实现加法运算
    char* add(char* data, char* addend, char* result);
    
    //此方法实现减法运算
    char* minus(char* data, char* sub, char* result);
    
    //此方法实现乘法运算
    char* multiply(char* data, char* mult, char* result);
    
    
    #endif // FUN_H_INCLUDED
    


    fun.c

    #include<stdio.h>
    #include<stdlib.h>
    #include"fun.h"
    #include<string.h>
    
    #define N 100
    
    //在此添加加法的实现
    char* add(char* data, char* addend, char* result)
    {
        int i=0,a1,a2;
        char pdata[2*N]={''};
        char padden[2*N]={''};//定义两个char类型的字符数组,并初始化每一位都置为''
        a1=strlen(data);
        a2=strlen(addend);//统计两个数组中字符串长度
        strcpy(pdata,data);//将字符串data复制到字符数组pdata[N]中
        strcpy(padden,addend);//将字符串addend复制到字符数组padden[N]中
    for(i=0;result!=''&&i<2*N;i++)//将字符数组result[2*N]初始化每一位都置为''
        {
          result[i]='';
        }
        if(pdata[0]!='-'&&padden[0]!='-')//当两个数均为正整数时
        {
          if(a1 >= a2)//第一个数的长度大于第二个数时
          {
            for(;a2>0;a2--,a1--)//两个正数对应位相加
            {
              result[a1-1]=pdata[a1-1]+padden[a2-1]-'0';//将相加得到的字符结果转化为数字字符
              if(result[a1-1]>'9'&&(a1-1)>0)//考虑进位的情况
              {
                result[a1-1] -= 10;
                pdata[a1-2]++;
              }
            }
            for(;a1>=1;a1--)//第一个数比第二个数多余的位数和'0'相加得到的结果
            {
              result[a1-1]=result[a1-1]+pdata[a1-1];
              if(result[a1-1]>'9'&&(a1-1)>0)
              {
                result[a1-1]-=10;//考虑到进位的情况
                pdata[a1-2]++;
              }
            }
            if(result[0]>'9')//当result[]中第一位>'9',要进行进位操作
            {
              a1=strlen(data);
              for(;a1>0;a1--)
              {
                result[a1]=result[a1-1];
              }
              result[1]-=10;
              result[0]='1';//首位进位加'1'
            }
          }
          else if(a1<a2)//第一个数的长度小于第二个数时,可以将加数与被加数调换再调用函数add()
          {       add(addend,data,result);
          }
        }
        else if(pdata[0]=='-'&&padden[0]=='-') //当为两个数都为负数时
        {
          result[0]='-';//result[]数组中第一位应为'-'
          add(&data[1],&addend[1],&result[1]);
        }
        else if(pdata[0]!='-'&&padden[0]=='-')//当第一个为正,第二个为负时,可以看做两个数相减,调用下面的minus()
        {
          minus(pdata,&padden[1],result);
        }
        else //当第一个为负,第二个为正时
        {
          add(addend,data,result);
        }
        return result;
    }//在此添加减法的实现
    char* minus(char* data, char* sub, char* result)
    {
        int i,b1,b2,p,dif;
        char pdata[N]={''}, psub[N]={''};
        strcpy(pdata,data);//将字符串data复制到字符数组pdata[N]中
        strcpy(psub,sub);//将字符串sub复制到字符数组psub[N]中
        for(i=0;result[i]!=''&&i<N;i++)//将字符数组result[2*N]初始化每一位都置为''
        {
          result[i]='';
        }
        b1=strlen(pdata);
        b2=strlen(psub);
        if(pdata[0]!='-'&&psub[0]!='-')//两个数都为正数
        {
          if(b1>b2)//第一个数位数大于第二个数时
          {
            for(;b2-1>=0;b1--,b2--)//两个正数对应位相减
     {
              result[b1-1]=pdata[b1-1]-psub[b2-1]+'0';//将相减得到的字符结果转化为数字字符
              if(result[b1-1]<'0')//考虑相减小于0的情况,要移位处理
              {
                result[b1-1]+=10;
                pdata[b1-2]--;
              }
            }
            p=b1;
            while (pdata[p-1]<'0'&&p>1)//当两个对应数相减小于'0'时,要位处理
            {
              pdata[p-1]+=10;
              pdata[p-2]--;
              p--;
            }
            if(b1>1)//第一个数比第二个数多余的位数和'0'相减得到的结果全部赋给result[]
            {
              for(;b1>0;b1--)
              {
                result[b1-1]=pdata[b1-1];
              }
            }
            while (result[0]=='0')//当移位相减后首位为'0'时
            {
              b1=strlen(pdata);
              for(i=0;i<=b1;i++)
              {
                result[i]=result[i+1];//要将result[]中的数都向前移一位
              }
            }
        }
        else if(b1 < b2)//第一个数位数大于第二个数时
    
        {
          result[0]='-';//result[]数组中第一位应为'-'
          minus(psub,pdata,&result[1]);//将减数与被减数置换,再调用minus()
     }
        else//第一个数位数等于第二个数时
        {
          if(pdata[0]!=psub[0])//考虑两个数组第一个数是否相等
          {
            for(i=0;pdata[i]!=psub[i];i++)
           {
              ;
           }
           dif=i;//如果不相等下标digit设为i
    
          }
          else
          {
            dif=0;//如果相等下标digit设为0
          }
          if(pdata[dif]>psub[dif])//当第一个数组中元素对应数值大于相同位的第二个数组中的元素
          {
            for(i=( b1-dif ) ; i > 0 ; i --,b1--,dif--)//对应位上的数值相减
            {
              result[b1-dif-1] =pdata[ b1-1 ] +'0'- psub[b2-1];//将相减得到的字符结果转化为数字字符
              if(result[b1-dif-1] < '0')
              {
                pdata[ b1-2 ]--;
                result[b1-dif-1] += 10;
              }
            }
            while (result[0]=='0')//当两个数组第一位数值相同,减去得到的结果为0
            {
              for(i = 0 ;i < b1-dif ; i++)//要将result[]数组中所有数向前移一位
              {
                result[i]=result[i+1];
              }
            }
          }
          else if(pdata[dif] < psub[dif])//当第一个数组中元素对应数值小于相同位的第二个数组中的元素
     {
            result[0]='-';//两个数组第一位元素相减对应数值小于0,想减结果第一位为'-'
            for(i = b1;i > 0 ; i--)
            {
              pdata[i] = pdata[i-1];//要pdata[]数组中所有数向后移一位
            }
              pdata[0] = '-';//相当于一个一个正数和一个负数做加法
              add(psub,&pdata[1],&result[1]);//调用加法函数add()
          }
          else//当第一个数组中元素对应数值等于相同位的第二个数组中的元素
          {
            result[0]='0';
            result[1]='';//最终result[]输出结果为0
          }
        }
       }
       else if(pdata[0]=='-'&&psub[0]!='-')//当第一个为负,第二个为正时,可以看做一个负数和一个正数做加法,调用加法函数add()
       {
         result[0]='-';
         add(&pdata[1],psub,&result[1]);
       }
       else if(pdata[0]!='-'&&psub[0]=='-')//当第一个为正,第二个为负时,可以看做一个正数和一个负数做加法,调用加法函数add()
       {
        add(pdata,&psub[1],result);
       }
       else
       {
        minus(&sub[1],&data[1],result);//当两个数都为负时,调用减法函数 minus()
       }
       return result;
    }
    //在此添加乘法的实现
     char *multiply(char* data, char* mult, char* result)
    {
        int digit,i,k,c1,c2,c3,num;
        char pdata[N]={''};
        char pmult[N]={''};//定义两个char类型的字符数组,并初始化每一位都置为''
        char array[2*N]={''};//定义一个数组array[],用来存放第二个数每位相乘第一个数得到的结果
        strcpy(pdata,data);//将字符串data复制到字符数组pdata[N]中
        strcpy(pmult,mult);//将字符串mult复制到字符数组pmult[N]中
        c1=strlen(data);
        c2=strlen(mult);//统计两个数组中字符串长度
        for(i=0;result[i]!=''&&i<2*N;i++)//将字符数组result[2*N]初始化每一位都置为''
        {
          result[i]='';
        }
        if(pdata[0]!='-'&&pmult[0]!='-')//当相乘的两个数均为正整数时
        {
          for(i=c1-1;i>=0;i--)
          {
            digit=c1-i-1;//统计array[]中需储存元素位数
            num=pdata[i]-'0';
            if(num>0)//当num>0时,将array[]先全部初始化每一位都置为''
            {
              for(k=0;array[k]!=''&&k<2*N;k++)
              {
                array[k]='';
              }
              for(;num>0;num--)//mult[]数组中每一位对应数值数,相应array[]中元素要乘以相同倍数,可以通过连续加法来实现
              {
                add(array,pmult,array);
              }
               c3=strlen(array);//重新统计新得到的数组array[]中字符串长度
              for(;digit>0;digit--)
    {
                array[c3+digit-1]='0';
              }
              add(array,result,result);//需将array[]中的元素错位累加即可得到最终相乘的结果
            }
          }
        }
        else if(pdata[0]=='-'&&pmult[0]!='-')//当第一个为负,第二个为正时,相乘结果第一位必为'-',再调用函数multiply[]
        {
          result[0]='-';
          multiply(&pdata[1],pmult,&result[1]);
        }
        else if(pdata[0]!='-'&&pmult[0]=='-')//当第一个为正,第二个为负时,相乘结果第一位必为'-',再调用函数multiply[]
        {
          result[0]='-';
          multiply(pdata,&pmult[1],&result[1]);
        }
        else if(pdata[0]=='-'&&pmult[0]=='-')//当两个数均为负整数时,相当于两个正整数相乘,调用函数multiply[]
        {
          multiply(&pdata[1],&pmult[1],result);
        }
        return result;
    }
    
    


     

  • 相关阅读:
    c#中的对象生命周期
    数据抓取的艺术(三):抓取Google数据之心得
    redmine3.3.0安装问题
    wget 无法建立ssl连接 [ERROR: certificate common name ?..ssl.fastly.net?.doesn?. match requested host name ?.ache.ruby-lang.org?. To connect to cache.ruby-lang.org insecurely, use ?.-no-check-certificate?]
    Centos安装ruby
    Redmine插件的安装与卸载,知识库插件安装。
    Nexus网页直接上传jar包
    mvn deploy命令上传包
    一辈子只有1次成为BAT的机会,你如何把握?
    redmine创建新闻,自动发邮件给项目组所有成员
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3233760.html
Copyright © 2020-2023  润新知