在《剑指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"); }