/*********************************************************************************************************
文件名称 : bignum.c
建立时间 : 2006-2-11 14:28
版权所有 : 东软股份大连分公司电信事业开发部
Author : 中介部.吴喆喆
文件描述 :
程序功能:大数之间的加减运算
接口函数:
char *Add(char *str1,char *str2); //大数str1加上大数str2
char *dec(char *str1,char *str2); //大数str1减去大数str2
说 明:
1. 这里所谓的大数是指大于2的31次方幂的正整数,用字符串表示
2. 测试减法的时候被减数大于减数
3. 例如 "78952584131420"+ "144897874655487"
= "223850458786907";
"144897874655487" - "78952584131420"
= "65945290524067";
4. 接口函数中原字符串不发生改变,返回值是计算结果
(字符串)的头指针
修改记录 :
========================================================================================================
序号 修改日期 修改人 修改原因
1. 2006-2-11 15:17 优化
*********************************************************************************************************/
#include <stdlib.h>
#include <string.h>
void reverse(char *);
void reverse(char *cret)
{
char ch;
int i;
int len;
i = 0;
len = strlen(cret);
while (i < strlen(cret)/2)
{
--len;
ch = cret[i];
cret[i] = cret[len];
cret[len] = ch;
++i;
}
}
char *Add(char *cstr1,char *cstr2)
{
char *bp1, *bp2;
char *ep1, *ep2;
int i1, i2, i3;
int flag = 0; /*flag表示进位*/
static char *ret;
char tmp[3];
char temp[100];
char str1[100]; /*cstr1的副本*/ /*创建副本的目的是为了有足够的空间进行交换, cstr1和cstr2长度不同所致*/
char str2[100]; /*cstr2的副本*/
strcpy(str1, cstr1);
strcpy(str2, cstr2);
/*为了下面的简化, 保持str1的长度始终小于等于str2的长度, 执行str1和str2的交换*/
if (strlen(str1) > strlen(str2))
{
strcpy(temp, str1);
strcpy(str1, str2);
strcpy(str2, temp);
}
bp1 = str1;
bp2 = str2;
ep1 = str1 + strlen(str1);
ep2 = str2 + strlen(str2);
ret = (char *)malloc(20);
memset(ret, 0, 20);
do
{
--ep1;
--ep2;
i1 = (*ep1) ^ '0';
i2 = (*ep2) ^ '0';
i3 = i1 + i2 + flag; /*flag表示进位*/
flag = 0; /*进位完后重置flag为0*/
sprintf(tmp, "%d", i3);
if (i3 < 10) /*无进位直接写入数组中*/
strcat(ret, tmp);
else /*有进位*/
{
++flag; /*表示有进位*/
memcpy(ret+strlen(ret), &tmp[1], 1);
}
} while (ep1 != bp1);
if (ep2 == bp2) /*必须要有, 这说明str2经过上面的已经到了最后一位, 可以返回了*/
{
if (flag != 0)
memcpy(ret+strlen(ret), &tmp[0], 1);
reverse(ret);
return ret;
}
else /*str2还有数字没拷贝完*/
{
do
{
--ep2;
if (flag != 0) /*有进位, 前面导致的*/
{
i2 = (*ep2) ^ '0';
i3 = i2 + flag;
flag = 0; /*flag重置*/
sprintf(tmp, "%d", i3);
if (i3 < 10) /*无进位*/
strcat(ret, tmp);
else
{
flag = 1;
memcpy(ret+strlen(ret), &tmp[1], 1);
if (ep2 == bp2) /*如果是最后的, 要加上进位*/
memcpy(ret+strlen(ret), &tmp[0], 1);
}
}
else /*没有进位就简单了, 这样就可以了*/
memcpy(ret+strlen(ret), ep2, 1);
} while (ep2 != bp2);
}
reverse(ret);
return ret;
}
char *Dec(char *cstr1,char *cstr2)
{
char *bp1, *bp2;
char *ep1, *ep2;
int i, i1, i2, i3;
int flag = 0, ch = 0; /*flag表示借位, ch表示是否借位*/
static char *ret;
char temp[100];
char str1[100]; /*cstr1的副本*/ /*创建副本的目的是为了有足够的空间进行交换, cstr1和cstr2长度不同所致*/
char str2[100]; /*cstr2的副本*/
strcpy(str1, cstr1);
strcpy(str2, cstr2);
/*为了下面的简化, 保持str1的长度始终小于等于str2的长度, 执行str1和str2的交换*/
if (strlen(str1) >= strlen(str2))
{
if (strlen(str1) == strlen(str2)) /*要使str2是较大的数, 如果有这样两个数9和6也是要交换的*/
{
for (i = 0; i < strlen(str1); ++i)
{
if (str1[i] > str2[i]) /*要使str2是较大的数, 如果有这样两个数19和16也是要交换的*/
{
strcpy(temp, str1);
strcpy(str1, str2);
strcpy(str2, temp);
ch = 1; /*表示交换过, 前面要有负号的*/
break;
}
}
}
else /*说明str1是大于str2的, 交换*/
{
strcpy(temp, str1);
strcpy(str1, str2);
strcpy(str2, temp);
ch = 1;
}
}
bp1 = str1;
bp2 = str2;
ep1 = str1 + strlen(str1);
ep2 = str2 + strlen(str2);
ret = (char *)malloc(20);
memset(ret, 0, 20);
do
{
--ep1;
--ep2;
i1 = (*ep1) ^ '0'; /*较小者*/
i2 = (*ep2) ^ '0'; /*较大者*/
if (i2 >= i1)
{
if ((i2 == i1) && flag) /*要借位*/
{
i2 += 10;
i3 = i2 - flag - i1;
}
else
{
i3 = i2 - flag - i1; /*flag表示借位*/
flag = 0;
}
}
else
{ if (flag && i2 == 0) //特殊情况, 100-99这种
{
i2 = 9; //借位减1后就是9了, 就是10-1
i3 = i2 - i1;
}
else
{
if (flag) //1010-999这种情况
--i2;
flag = 1;
i2 += 10;
i3 = i2 - i1;
}
}
sprintf(ret+strlen(ret), "%d", i3);
} while (ep1 != bp1);
--ep2;
while (ep2 >= bp2)
{
i2 = *ep2 ^ '0';
if (flag)
{
if (i2 >= flag)
{
sprintf(ret+strlen(ret), "%d", i2-flag);
flag = 0;
}
else
{
flag = 1;
i2 += 10;
i3 = i2 - flag;
sprintf(ret+strlen(ret), "%d", i3);
}
}
else
sprintf(ret+strlen(ret), "%d", i2);
--ep2;
}
if (ch)
sprintf(ret+strlen(ret), "%s", "-");
reverse(ret);
return ret;
}
int main(void)
{
//char str1[] = "144897874655487";
//char str2[] = "78952584131420";
char str1[] = "99";
char str2[] = "1000";
char *p;
p = Dec(str1, str2);
printf("%s/n", p);
}