面试题整理3 大数的表示及加减法问题

在《剑指offer》面试题12中指出大数的表示时一般用字符串,用一个char型字符表示十进制数的一位。但是一个char类型最多能够表示256个字符,而十进制数只有0~910个数字,这样造成内存浪费。可以采用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");

}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值