大整数乘法以及空间性能优化

        在C++版的数据结构中有一道课后练习题—大整数求和,不过这次我想弄的是大整数乘法并对它进行空间性能优化一下,因为书本上的一个int类型只能存放0~9的数字,很容易造成空间上的浪费,这次我的一个int类型存放4位数字,不过在实现之前我们还是做一下大整数加法,毕竟要先从容易的入手,题目如下所示: 

        用某种程序设计语言进行编程时,可能需要处理非常大或者运算精度要求非常高的整数(称为大整数),这种大整数用该语言的基本数据类型是无法直接表示的。处理大整数的一般方法是用数组存储大整数,数组元素代表大整数的一位,通过数组运算模拟大整数的运算。

        以上为题目: 首先我来说一下我的解题思路: 

        1. 创建一个char类型的数组,接收键盘的输入,当然我也百度了一下其他人的博客,他们都是直接建立int类型的数组的,其实这样子并不是很好,因为当我们输入123时,如果直接用int类型数组,每输入一个数子都要加一个空格分开了,即输入1  2  3,这样子会导致输入很不方便,所以这次我用的是char数组再转换为int数组。

        2. 数组的中的排序为从低位到高位,即123在数组用321来表示,因为加法运算时是从低位算起的。

        具体代码如下: 

#include <iostream>
#include <cstring>
using namespace std;

const int Max_size = 100000;

int num1[Max_size];    
int num2[Max_size];      
int sum[Max_size];

//加法函数
void add(){
      int max;
      //为了方便相加,将数组长度短的后面初始化为0 
      if(num1[Max_size-1]<num2[Max_size-1]){
            for(int i=num1[Max_size-1];i<num2[Max_size-1];i++){
                  num1[i] = 0;
            } 
            max = num2[Max_size-1];
      }else{
            for(int i=num2[Max_size-1];i<num1[Max_size-1];i++){
                  num2[i] = 0;
            }
            max = num1[Max_size-1];
      }
      sum[Max_size-1] = max;
      for(int i=0;i<max-1;i++){
            sum[i] = num1[i]+num2[i];
            //进位
            //感觉当时应该把num1,num2传进来的,现在num1已经被污染了
            //(PS: 不能以int* 的方式传数组,因为以指针的方式一样会被污染的)
            if(sum[i]>9){
                  sum[i] -= 10;
                  num1[i+1]++; 
            }
      }
      sum[max-1] = num1[max-1]+num2[max-1];
      if(sum[max-1]>9){
            sum[max-1] -= 10;
            sum[max] = 1;
            sum[Max_size-1]++;
      }
}

int main(){
      char num[Max_size];     //输入的字符转换为数字
      cin>>num;
      //将数组的高位存放数字的低位
      for(int i=strlen(num)-1;i>=0;i–){
            //将char类型隐式转换为int类型
            num1[strlen(num)-1-i] = num[i]-‘0’;
            //这是一个错误的示范,其实应该将strlen(num) 赋值给一个整型的
            //因为用一个调用strlen()函数真的很耗性能   
      }
      //用数组的最后一个存放该数组的长度 
      num1[Max_size-1] = strlen(num);
      //给num2数组赋值,重复以上步骤
      cin>>num;
      for(int i=strlen(num)-1;i>=0;i–){ 
            num2[strlen(num)-1-i] = num[i]-‘0’;    
      }
      num2[Max_size-1] = strlen(num); 
      add();
      for(int i=sum[Max_size-1]-1;i>=0;i–){
            cout<<sum[i];
      }
      return 0;
}

上面为大整数加法,下面来讨论大整数乘法,在实现之前先说一下我的思路: 

        1. 当我们输入123456789(char类型)时,6789存放在int[0]中,2345存放在int[1]中,1存放在int[2]中,因为输入的char类型,所以要将四个字符转为四位数字(即千位数),但前面都是存放4个字符,可以用统一的代码来实现,但最后一个1只有一个字符,需要特殊处理一下。(其实也不用这样处理的,只需在char数组前留空几个字符就可以,可以参考一下链表中使用空头结点来统一代码的思路)

        2. 当输出结果时,有些存放的数字是0123,真正输出的是123,所以要做一些处理,将其转换一下。

        3. 刚开始做这道题时,我以为跟大整数求和的差不多,其实这道题并是很简单的,有很多需要注意的问题,有兴趣的可以做下。

具体代码如下: 

#include <iostream>
#include <cstring>
using namespace std;

const int Max_size = 10000;
char num[Max_size*4];
int num1[Max_size] = {0};
int num2[Max_size] = {0};
int sum[Max_size*2] = {0};
int num1_len,num2_len,sum_len,num_len;

void char_to_int(int i,int* a){
      int n=1;
      int temp=num_len-1-4*i;
      if(temp<3)       //递归的结束条件 
            return;
      for(int j=0;j<4;j++){
            int m = num[temp] – ‘0’;
            *a += n*m;
            n *= 10;
            temp–;
      }
      char_to_int(++i,++a);
}

void mutil(){
      sum_len = 0;
      for(int i=0;i<num1_len;i++){
            for(int j=0;j<num2_len;j++){
                  long n = num1[i]*num2[j];
                  sum[i+j] += n%10000;
                  sum[i+j+1] += n/10000;
                  if(sum_len<i+j+2){
                  sum_len = i+j+2;
                  }
                  if(sum[i+j]>9999){
                        sum[i+j] -= 10000;
                        sum[i+j+1] += 1;
                  }
            }
      }
      if(!sum[sum_len-1]){
            sum_len–;
      }
}

int main(){
      int start,n,m;
      cin>>num;
      num_len = strlen(num);
      start = num_len%4-1;
      num1_len = (num_len-1)/4+1;
      n = 1;
      while(start != -1){
            m = num[start] – ‘0’;
            num1[num1_len-1] += n*m;
            n *= 10;
            start–;
      } 
      //这次我用的递归函数处理…(传入的i为给第i个数组赋值) 
      char_to_int(0,num1);
      //重复上述步骤,给num2赋值
      cin>>num;
      num_len = strlen(num);
      start = num_len%4-1;
      num2_len = (num_len-1)/4+1;
      n = 1;
      while(start != -1){
            m = num[start] – ‘0’;
            num2[num2_len-1] += n*m;
            n *= 10;
            start–;
      }
      char_to_int(0,num2);
      mutil();
      cout<<sum[sum_len-1];
      for(int i=sum_len-2;i>=0;i–){
            if(sum[i]<10){
                  cout<<“000”;
            }else if(sum[i]<100){
                  cout<<“00”;
            }else if(sum[i]<1000){
                  cout<<“0”;
            }
            cout<<sum[i];
      }
      return 0;
}

    原文作者:大整数乘法问题
    原文地址: https://blog.csdn.net/qq_35043757/article/details/53354000
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞