在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;
}