大数相加(C实现)

renzhewh 2010-03-28 03:37:58
题目:规定输入的数字长度不超过256.

注:程序中输入、输出使用字符串存储,使用了vs中扩展的函数 strrev(亦可自己实现);

此外为了操作方便对给定的输入数字进行了反转,因此只能针对非只读字符串。

源码如下:

#include <stdio.h>
#include <string.h>

enum {MAXSIZE = 256 + 2, RADIX = 10};

/* ans = first + second */
char *big_num_add(char *ans, char *first, char *second)
{
int i = 0; /* ans 的索引 */
int carry = 0; /* 进位, 初始为0 */

char *strA = strrev(first);
char *strB = strrev(second);

do
{
carry += (*strA &0xf) + (*strB & 0xf);
ans[i++] = carry % RADIX + '0';
carry /= RADIX;
} while (*strA++ || *strB++);

strrev(first);
strrev(second);

return strrev(ans);
}


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/renzhewh/archive/2010/03/28/5424744.aspx
...全文
1670 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
寸人 2010-11-11
  • 打赏
  • 举报
回复
#include<stdio.h>
#include<string.h>
void mod(int a[],int m,int n,int b[])
{
int k=m;
m--;
for(int i=n-1;i>0;i--)
{
a[m]=a[m]+b[i];
if(a[m]>=10)
{
a[m-1]+=1;
a[m]-=10;
}
m--;
}
for(int l=k-n;l>0;l--)
{
if(a[l]>=10)
{
a[l-1]+=1;
a[l]-=10;
}
else break;
}
if(a[0]==1)
printf("%d",a[0]);
for(int j=1;j<k;j++)
printf ("%d",a[j]);
printf("\n");
}

int a1[1005],b1[1005];
int main()
{
//freopen("input.txt","r",stdin);

char cn;
while(scanf("%c",&cn)==1)
{
memset(a1,0,sizeof(a1));
memset(b1,0,sizeof(b1));
int i=1,j=1;

a1[0]=b1[0]=0;
while(cn!=' ')
{
a1[i]=cn-'0';
i++;
scanf("%c",&cn);
}
while(scanf("%c",&cn)==1)
{
if (cn=='\n')break;
else
{
b1[j]=cn-'0';
j++;
}
}

if(i>j)
mod(a1,i,j,b1);
else
mod(b1,j,i,a1);
}
return 0;
}
zhangnala91 2010-04-06
  • 打赏
  • 举报
回复
没有令人满意的结果
renzhewh 2010-04-02
  • 打赏
  • 举报
回复
有人看过《C 接口与实现》吗?
它上面的大数运算如何实现的?
FoxSerratifolia 2010-04-02
  • 打赏
  • 举报
回复
没看过,谁有可以联系我下,学习过程中
cwh5635 2010-03-31
  • 打赏
  • 举报
回复
mark,自己刚用指针写完大数加减乘除。。。。。。比较一下
renzhewh 2010-03-31
  • 打赏
  • 举报
回复
回17#
说的对
yaoming1718 2010-03-31
  • 打赏
  • 举报
回复
4# 的代码学习了 ,但是 && 也是先判断 左边,左边为空时,右边就不判断了 ,所以程序有错,不知道说的对不对?
renzhewh 2010-03-31
  • 打赏
  • 举报
回复
回11#
我知道可能会造成溢出。
但在特定场合下,比如将输入限定在长度为MAZXSIZE的字串,且已清0的情况下,
就可以使用这种方法。
此外,希望各位考虑如果进制为16,那么如何以最小的代码改动量达到目的?
zhu_nn 2010-03-28
  • 打赏
  • 举报
回复
lz的代码支持小数相加吗?不行吧
yiruirui0507 2010-03-28
  • 打赏
  • 举报
回复
个人感觉上述代码也算很好的了!
yuxh81 2010-03-28
  • 打赏
  • 举报
回复
代码好短啊,比我写的少了一半!

很好啊!!!
delphiwcdj 2010-03-28
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 huanmie_09 的回复:]
引用 9 楼 renzhewh 的回复:
回7#
你看我修改后的代码,不存在你说的问题;
另外使用运算符||,是为了减少代码,因此出现了
carry += (*strA++ &amp;0xf) + (*strB++ &amp; 0xf);
这段代码,而没有使用
carry += (*strA++ - '0') + (*strB++ - '0')
因为需要考虑strA、……
[/Quote]
up
huanmie_09 2010-03-28
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 renzhewh 的回复:]
回7#
你看我修改后的代码,不存在你说的问题;
另外使用运算符||,是为了减少代码,因此出现了
carry += (*strA++ &0xf) + (*strB++ & 0xf);
这段代码,而没有使用
carry += (*strA++ - '0') + (*strB++ - '0')
因为需要考虑strA、strB中有一个出现0(ASCII)的情况
[/Quote]
你不觉得有越界的嫌疑么。
这样,就打个比方strA="123", strB="1",
按你的运算3跟1相加之后, strB++,这时strB指向字符串结束符'\0', 再加一次, 就不属该字符串的值了。
renzhewh 2010-03-28
  • 打赏
  • 举报
回复
我对此有个问题,本代码中写的进制是10,如果是16进制或者20进制,怎么才能以最小的代码改动
达到目的?
renzhewh 2010-03-28
  • 打赏
  • 举报
回复
回7#
你看我修改后的代码,不存在你说的问题;
另外使用运算符||,是为了减少代码,因此出现了
carry += (*strA++ &0xf) + (*strB++ & 0xf);
这段代码,而没有使用
carry += (*strA++ - '0') + (*strB++ - '0')
因为需要考虑strA、strB中有一个出现0(ASCII)的情况
renzhewh 2010-03-28
  • 打赏
  • 举报
回复
我对此有个问题,本代码中写的进制是10,如果是16进制或者20进制,怎么才能以最小的代码改动
达到目的?
huanmie_09 2010-03-28
  • 打赏
  • 举报
回复
同时,不要忘记了||运算符的短路性质,strA自增后,当判断strA*不为结束符后,后面的strB根本不会自增, 也就不会判断。
你让两个字符串相加,必须要两个串指针同时自增啊。
所以要用&&操作符。
这里的循环退出后,还要对没有处理的字符串进行处理。
renzhewh 2010-03-28
  • 打赏
  • 举报
回复
回4#
while (*(++strA) && *(++strB)); /*指针先自增,后判断*/
这句应该不对,考虑两个空串,这样会出现溢出。
renzhewh 2010-03-28
  • 打赏
  • 举报
回复
回4#,说的对,我之前使用的是while,后来考虑少写些代码,改为do while
对于上述问题,按照你的想法,加的代码太多
我原先的做法是

#include <stdio.h>
#include <string.h>

enum {MAXSIZE = 256 + 2, RADIX = 10};

/* ans = first + second */
char *big_num_add(char *ans, char *first, char *second)
{
int i = 0; /* ans 的索引 */
int carry = 0; /* 进位,初始为0 */

char *strA = strrev(first);
char *strB = strrev(second);

while (*strA || *strB)
{
carry += (*strA++ &0xf) + (*strB++ & 0xf);
ans[i++] = carry % RADIX + '0';
carry /= RADIX;
}
if (carry)
ans[i++] = carry + '0';
ans[i] = 0;

strrev(first);
strrev(second);

return strrev(ans);
}
huanmie_09 2010-03-28
  • 打赏
  • 举报
回复
楼主请将算法更新一下,do..while循环里的条件while (*strA++ || *strB++); 是不行的,
do..while先循环一次,而判断*strA++相当于是:先判断*strA是否等于0, 然后strA++;
同时,不要忘记了||运算符的短路性质,当判断strA*不为结束符后,strA++, 后面的strB根本就不会判断,也不会自增。
楼主可以自己验证一下,当传入的参数first="123", second="1"时,将会计算出什么结果。
在楼主的代码基础上,我稍作了一点修改,贴出来供楼主参考:

#include <stdio.h>
#include <string.h>

enum {MAXSIZE = 256 + 2, RADIX = 10};

/* ans = first + second */
char *big_num_add(char *ans, char *first, char *second)
{
int i = 0; /* ans 的索引 */
int carry = 0; /* 进位, 初始为0 */

char *strA = strrev(first);
char *strB = strrev(second);
do
{
carry += (*strA &0xf) + (*strB & 0xf);
ans[i++] = carry % RADIX + '0';
carry /= RADIX;
} while (*(++strA) && *(++strB)); /*指针先自增,后判断*/
while(*strA){ /*如果strA里还有字符*/
ans[i++] = *strA++;

}
while(*strB) {
ans[i++] = *strB++;
}
ans[i] = '\0'; /*添加结束符*/
strrev(first);
strrev(second);

return strrev(ans);
}

int main()
{
char first[255] = "123";
char second[255] = "123232323";
char ans[256];
big_num_add(ans, first, second);
printf("ans=%s\n", ans);
return 0;
}
加载更多回复(3)

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧