在《剑指offer》面试题12中指出大数的表示时一般用字符串,用一个char型字符表示十进制数的一位。但是一个char类型最多能够表示256个字符,而十进制数只有0~9的10个数字,这样造成内存浪费。可以采用256进制的表示方法,这样不会有内存空间的浪费。但是如果针对题目中以十进制打印的话,这样还需要数据的转换,效率太低。
空间和时间往往不能两全其美,针对不同的需求有不同的选择。
题目:实现两个整形的加法。
分析:这是一个大数问题,照样使用字符串来表示大数。
需要注意,正负号怎么表示,计算时怎样处理。同时注意边界和效率问题。
思路:
数据的表示结构,一个字符串表示权重,一个标志表示正负号。
(1)若其中一个为0,则结果为另一个。
(2)若两数同号,保留符号,将权值相加即可。
(3)若两数异号,则先比较两数的权重大小:
若权重相同,则返回0;
若一大一小,则保留权重大的符号,值为大值减小值。
小女不才,写了一个大数的加法运算,测试通过,还望大家指正。
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
struct BigInt{
bool isNegative;
char* data; // always positive
BigInt():isNegative(false),data(NULL){}
BigInt(bool isNegative, char data[])
{
this->isNegative = isNegative;
this->data = data;
}
};
char* subtractCharArray( const char param1[], const char param2[]);
char* addCharArray( const char param1[], const char param2[]);
BigInt addBigInt(const BigInt& parameter1, const BigInt& parameter2);
int compare(const char param1[],const char param2[] );
BigInt addBigInt(const BigInt& parameter1, const BigInt& parameter2)
{
BigInt resultBigInt;
//if null
if(parameter1.data == NULL || parameter2.data == NULL)
{
cout << "parameter is null" << endl;
return resultBigInt;
}
// if one is zero
if(compare(parameter1.data,"0") == 0 )
{
resultBigInt.data = parameter2.data;
return resultBigInt;
}
if(compare(parameter2.data,"0") == 0 )
{
resultBigInt.data = parameter1.data;
return resultBigInt;
}
// the sign is same
if( parameter1.isNegative == parameter2.isNegative)
{
resultBigInt.isNegative = parameter1.isNegative;
resultBigInt.data = addCharArray(parameter1.data,parameter2.data);
return resultBigInt;
}
// the sign is not same
switch(compare(parameter1.data,parameter2.data))
{
case 1: //greater
resultBigInt.isNegative = parameter1.isNegative;
resultBigInt.data = subtractCharArray(parameter1.data,parameter2.data);
break;
case -1: //smaller
resultBigInt.isNegative = parameter2.isNegative;
resultBigInt.data = subtractCharArray(parameter2.data,parameter1.data);
break;
case 0:
resultBigInt.data = new char[2];
resultBigInt.data[0] = '0';
resultBigInt.data[1] = '\0';
}
return resultBigInt;
}
// if param1 > param2 ,return 1;
// if param1 < param2 ,return -1;
// if param1 = param2 ,return 0;
int compare(const char param1[],const char param2[] )
{
int length1 = strlen(param1);
int length2 = strlen(param2);
if( length1 > length2 )
{
return 1;
}
if( length1 < length2 )
{
return -1;
}
for( int i=0; i<= length1; ++i)
{
if(param1[i]>param2[i])
{
return 1;
}else if(param1[i]<param2[i])
{
return -1;
}
}
return 0;
}
char* addCharArray( const char param1[], const char param2[])
{
int length1 = strlen(param1);
int length2 = strlen(param2);
//one is null
if(length1 == 0)
{
return const_cast<char*>(param2);
}else if(length2 == 0)
{
return const_cast<char*>(param2);
}
//maxlength
int maxLength = max(length1,length2);
// extra 2 bits, one is for '\0', one is for carry
char* result = new char[maxLength+2];
result[maxLength+1] = '\0';
int nTakeOver = 0; // carry flag
for(int i = maxLength,j=length1-1,k=length2-1; i>=0; --i,--j,--k)
{
if( j < 0 && k < 0) // in this sitation once at most
{
result[i] = nTakeOver + '0';
break;
}
int nSum = 0;
if(j >= 0 && k < 0) // only paramter1.data has left bits
{
nSum = param1[j] + nTakeOver;
}else if(j < 0 && k >= 0) // only paramter2.data has left bits
{
nSum = param2[k] + nTakeOver;
}else
{
nSum = param1[j]-'0'+param2[k]-'0'+nTakeOver;
}
if(nSum >= 10)
{
nTakeOver = 1;
nSum -= 10;
result[i] = nSum + '0';
}else
{
nTakeOver = 0;
result[i] = nSum + '0';
}
}
if( nTakeOver == 1){ // if have a carry ,the MSB is 1
return result;
}else // the MSB is 0, decrease the length.
{
char* finalResult = new char[maxLength+1];
strcpy(finalResult,result+1);
delete[] result;
return finalResult;
}
}
//param1 - param2 ,unsigned BigInter
// make sure param1 is larger than param2
char* subtractCharArray( const char param1[], const char param2[])
{
int length1 = strlen(param1);
int length2 = strlen(param2);
if(length1 < length2 || compare(param1,param2) < 0)
{
throw new exception("invalid input");
}
int maxLength = length1;
// maxLength at most, one extra bit is saved for '\0'
char* result = new char[maxLength+1];
result[maxLength] = '\0';
// carry flag
int nTakeOver = 0;
for(int i = maxLength-1,j=length1-1,k=length2-1; i>=0; --i,--j,--k)
{
int nSum = 0;
if(j >= 0 && k < 0) // only param1.data has left bits
{
nSum = param1[j] - '0'- nTakeOver;
}else
{
nSum = param1[j]- param2[k]- nTakeOver;
}
if(nSum < 0)
{
nTakeOver = 1;
nSum += 10;
result[i] = nSum + '0';
}else
{
nTakeOver = 0;
result[i] = nSum + '0';
}
}
//count the number of zeros at the beginning of the array
int index = 0;
while(result[index]=='0')
{
++index;
}
//if no zero
if( index == 0){
return result;
}
//remove zeros at the beginning of the array
int finalLength = maxLength+1-index;
char* finalResult = new char[finalLength];
strcpy(finalResult,result+index);
delete[] result;
return finalResult;
}
int main()
{
//one is zero or null
char* data0 = "0";
BigInt bigData0 = BigInt(false,data0);
char* data1 = "933900000000000000000000000009";
BigInt bigData1 = BigInt(false,data1);
BigInt addResultBigInt0 = addBigInt(bigData0,bigData1);
//positive test
BigInt bigData2 = BigInt(false,data1);
BigInt addResultBigInt1 = addBigInt(bigData1,bigData2);
// one positive ,one negative test
// equal
BigInt bigData3 = BigInt(true,data1);
BigInt addResultBigInt2 = addBigInt(bigData1,bigData3);
// one positive ,one negative test
char* data2 = "933900000000000000000000000008";
BigInt bigData4 = BigInt(true,data2);
BigInt addResultBigInt3 = addBigInt(bigData4,bigData1);
system("pause");
}