首页 > 代码库 > 正数相减少

正数相减少

技术分享

技术分享

我开始用的代码:

/******************************************************************************

  Copyright (C), 2001-2011, Huawei Tech. Co., Ltd.

 ******************************************************************************
  File Name     : 
  Version       : 
  Author        : 
  Created       : 2009/10/10
  Last Modified :
  Description   : 
  Function List :
              
  History       :
  1.Date        : 2009/10/10
    Author      : 
    Modification: Created file

******************************************************************************/
#include <stdlib.h>

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int a[40]={0},b[40]={0};
int term[40]={11};
//有效数字从 [0,j)开始的  return :the position小数点 c[i]=11处
int partition(const char* s,int c[])
{
	int len=strlen(s);
	int j=0;
	for(int i=0;i<len;i++)
	{
		switch(s[i])
		{
		case '0':
			if(j==0)
			{
				c[j]=11;
				j--;
				break;
			}else
			{
				a[j]=0;
				break;
			}
		case '1':c[j]=1;break;
		case '2':c[j]=2;break;
		case '3':c[j]=3;break;
		case '4':c[j]=4;break;
		case '5':c[j]=5;break;
		case '6':c[j]=6;break;
		case '7':c[j]=7;break;
		case '8':c[j]=8;break;
		case '9':c[j]=9;break;
		case '.':c[j]=10;break;
		}
		j++;
		c[j]=11;
	}
	c[j]=11;
	int i;
	for(i=0;c[i]!=11;i++)
	{
		if(c[i]==10) return i;
	}
	return i;
	
}

double  sub(int *a,int *b,int e,int k,int e2,int k2)
{
	int l=(e-k)>(e2-k2)?(e-k):(e2-k2);//包含小数点到后面的长度
	int l2=k>k2?k:k2;//小数点前的长度
	int len=l+l2;
	for(int i=0;i<len;i++)
		term[i]=0;
	for(int i=1;i<l;i++)
	{
		if(k+i>=e)
			a[k+i]=0;
		if(k2+i>=e2)
			b[k2+i]=0;
		term[l2+i]=a[k+i]-b[k2+i];
	}
	term[l2]=10;
	for(int i=0;i<l2;i++)
	{
		if(k2-i-1<0)
		{
			term[l2-i-1]=a[k-i-1];
		}else
			term[l2-i-1]=a[k-i-1]-b[k2-i-1];
	}

	//处理进位
	for(int i=len-1;i>=0;i--){
		
		if(term[i]<0)
		{
			if(term[i-1]==10)
			{
				term[i-2]=term[i-2]-1;
			}else
				term[i-1]=term[i-1]-1;
			term[i]+=10;
		}
	
	}
	

	
	string str;
	for(int i=0;i<len;i++)
	{
		char ch;
		if(term[i]==10)
			ch='.';
		else
			ch=term[i]+'0';
		str+=ch;
	}
	//cout<<str<<endl;
	stringstream stream(str);
	double d;
	stream>>d;
	return d;
	
}
double Decrease2(const char *s,const char *s2)//假设s>s2
{
	int k=partition(s,a);
	int i,e,e2,h,h2;//h表示从小数点开始的长度
	for(i=0;a[i]!=11;i++);
	e=i;//[0,e) 小数点位置在k
	h=e-k;

	int k2=partition(s2,b);
	for(i=0;b[i]!=11;i++);
	e2=i;
	h2=e2-k2;

	return sub(a,b,e,k,e2,k2);


}

int cmp(int a[],int b[],int k,int k2)//比较 a[0..k) 到b[0,..k2)
{
	if(k>k2) return 1;
	if(k<k2) return -1;
	for(int i=0;i<k;i++)
	{
		if(a[i]==b[i])
			continue;
		if(a[i]>b[i])
			return 1;
		else
			return -1;
	}
	return 0;
}
int Judge(const char *s, const char *s2)//判断正负数
{
	int k=partition(s,a);
	int i,e1,e2,h,h2;//h表示从小数点开始的长度
	for(i=0;a[i]!=11;i++);
	e1=i;//[0,e) 小数点位置在k
	h=e1-k;

	int k2=partition(s2,b);
	for(i=0;b[i]!=11;i++);
	e2=i;
	h2=e2-k2;

	/*比较整数部分*/
	int res=cmp(a,b,k,k2);
	if(res!=0)
		return res;
	if(e1<e2)
	{
		for(i=0;i<e2-e1;i++)
		{
			a[e1+i]=0;
		}
	}else if(e1>e2)
	{
	
		for(i=0;i<e1-e2;i++)
			b[e2+i]=0;
	}
	int e=e1>e2?e1:e2;
	res=cmp(a,b,e,e);
	return res;

}
/*****************************************************************************
Description  : 两个任意长度的正数相减
Prototype    : int Decrease(const char *pMinuend, const char *pSubtrahend, char **ppResult)
Input Param  : const char *pMinuend     被减数,以\0表示字符串结束
               const char *pSubtrahend  减数,以\0表示字符串结束
Output       : char **ppResult          减法结果,必须以\0表示字符串结束
Return Value : 成功返回0   失败返回-1
*****************************************************************************/
int Decrease(const char *pMinuend, const char *pSubtrahend, char **ppResult)
{

    /* 在这里实现功能 */
	if(pMinuend == NULL || pSubtrahend == NULL || pMinuend[0] == '\0' || pSubtrahend[0] == '\0')
		return -1;
	 double d;
	 int flg=Judge(pMinuend,pSubtrahend);
	 if(flg==1)
		 d=Decrease2(pMinuend,pSubtrahend);
	 else if(flg==-1)
		 d=Decrease2(pSubtrahend,pMinuend);
	 else 
	 {
		 *ppResult=new char[2];
		 (*ppResult)[0]='0';
		 (*ppResult)[1]='\0';
		 return 0;
	 }
	 if(flg==-1)
		 d=-1*d;
	//cout<<"d="<<d<<endl;
	char out[100]={0};
	
	stringstream stream;
	stream<<d;
	stream>>out;//  可能溢出了  没法解决
	int len=strlen(out);
	*ppResult=new char[len+1];
	sprintf(*ppResult,"%s",out);
	(*ppResult)[len]='\0';

	//cout<<*ppResult<<endl;
    return 0;

}

结果提交上去,20个例子通过13个,我没有想到任何大的数据 用string 表示,

首先用一个函数表示一个大数-小数,a>b  a-b

将a=aa.ab    b=ba.bb

拆分

首先减法,后进位

比如 1234.34  -  987.45   正数部分 1 -3 -5 -3   小数部分 -1 -1

进位操作:    小数  8 9   正数            0 6  4  6

去掉没用的0 即可

具体代码如下:

string Decrease3(string aa,string ab,string ba,string bb)//a>b 的时候  aa.ab  ba.bb
{
	int len=aa.length()>ba.length()?aa.length():ba.length();//整数部分的长度
	int len2=ab.length()>bb.length()?ab.length():bb.length();//小数部分的长度
	int* A=new int[len];
	int *B=new int[len2];
	int i,Carry=0;


	/*整数部分*/
	int aa_length=aa.length();
	int ba_length=ba.length();
	for(i=0;i<len;i++)
	{
		if(ba_length-i-1<0)
		{
			A[len-i-1]=aa[aa_length-i-1]-'0';
		}else
			A[len-i-1]=aa[aa_length-i-1]-ba[ba_length-i-1];
	}
	
	
	/*小数部分*/
	int ab_length=ab.length();
	int bb_length=bb.length();
	for(int i=0;i<len2;i++)
	{
		if(i>ab_length-1)
			B[i]='0'-bb[i];
		else if(i>bb_length-1)
			B[i]=ab[i]-'0';
		else
			B[i]=ab[i]-bb[i];

	}

	
	

	/*处理进位*/
	
	for(i=len2-1;i>=0;i--)
	{
		if(B[i]<0)
		{
			if(i-1>=0)
			{
				B[i-1]=B[i-1]-1;
			}else
				Carry=-1;
			B[i]+=10;
		}
	}
	if(Carry==-1)
		A[len-1]=A[len-1]-1;
	for(i=len-1;i>=0;i--)
	{
		if(A[i]<0)
		{
			A[i-1]=A[i-1]-1;
			A[i]=A[i]+10;
		}
	}

	string res="";
	char ch;
	for(i=0;i<len;i++)
	{
		ch=A[i]+'0';
		res=res+ch;
	}
	res=res+".";
	for(i=0;i<len2;i++)
	{
		ch=B[i]+'0';
		res=res+ch;
	}


	/*delete zero    xxx.xxx0000*/
	
	size_t pos=res.find_first_of(".");
	int s2,t2;
	for(s2=0;s2<res.length();s2++)
	{
		if(res[s2]>'0'&&res[s2]<='9')
			break;
	}
	for(t2=res.length()-1;t2>=0;t2--)
	{
		if(res[t2]>'0'&&res[t2]<='9')
			break;
	}
	string tmp="";
	if(pos<s2)
	{
		tmp=res.substr(pos-1,res.length()-pos+1);
	}else
		tmp=res.substr(s2,t2-s2+1);
	


	delete A;
	delete B;

	return tmp;



}



/*****************************************************************************
Description  : 两个任意长度的正数相减
Prototype    : int Decrease(const char *pMinuend, const char *pSubtrahend, char **ppResult)
Input Param  : const char *pMinuend     被减数,以\0表示字符串结束
               const char *pSubtrahend  减数,以\0表示字符串结束
Output       : char **ppResult          减法结果,必须以\0表示字符串结束
Return Value : 成功返回0   失败返回-1
*****************************************************************************/
int Decrease(const char *pMinuend, const char *pSubtrahend, char **ppResult)
{

    /* 在这里实现功能 */
	if(pMinuend == NULL || pSubtrahend == NULL || pMinuend[0] == '\0' || pSubtrahend[0] == '\0')
		return -1;
	string a=pMinuend;
	string b=pSubtrahend;
	string aa="";
	string ab="";
	string ba="";
	string bb="";
	size_t a_index=a.find_first_of(".");
	size_t b_index=b.find_first_of(".");
	aa=a.substr(0,a_index);//[0,a_index)
	if(a_index!=string::npos)
		ab=a.substr(a_index+1,a.length()-a_index-1);//[a_index+1,a.length())
	
	ba=b.substr(0,b_index);//[0,a_index)
	if(b_index!=string::npos)
		bb=b.substr(b_index+1,b.length()-b_index-1);//[b_index+1,b.length())
	int flg=0;//符号 a>b 1  a<b -1  a==b 为0
	
	if(aa.length()>ba.length())
	{
		flg=1;
	}else if(aa.length()<ba.length())
	{
		flg=-1;
	}else// 整数部分的位数相等
	{
		flg=aa>ba?1:-1;
		if(aa>ba)
			flg=1;
		else if(aa<ba)
			flg=-1;
		else
			flg=0;


		if(flg==0)
		{
			if(ab==bb)
				flg=0;
			else if(ab>bb)
				flg=1;
			else
				flg=-1;
		}
	
	}

	string res;
	
	if(flg==0)
	{
		
		*ppResult=new char[2];
		(*ppResult)[0]='0';
		(*ppResult)[1]='\0';
		return 0;
	}else if(flg==1)
	{
		res=Decrease3(aa,ab,ba,bb);
	}else
	{
		res=Decrease3(ba,bb,aa,ab);
		res="-"+res;

	}

	int len=res.length();
	*ppResult=new char[len+1];
	char *p=*ppResult;
	for(int i=0;i<len;i++)
	{
		*p=res[i];
		p++;
	}
	*p='\0';

    return 0;

}


    


正数相减少