超长正整数减法,错在哪里???

abckangaroo 2009-08-13 04:16:19
哪一步没有考虑到,或者有什么更好的算法???
望高人指点~~~~


/*
【问题描述】
编写程序实现两个超长正整数(每个最长80位数字)的减法运算。

【输入形式】
从键盘读入两个整数,要考虑输入高位可能为0的情况(如00083)。
1. 第一行是超长正整数A;
2. 第二行是超长正整数B;

【输出形式】
输出只有一行,是长整数A减去长整数B的运算结果,从高到低依次输出各位数字。
要求:若结果为0,则只输出一个0;否则输出的结果的最高位不能为0,并且各位数字紧密输出。
【输入样例】

234098
134098703578230056

【输出样例】
-134098703577995958
【样例说明】
进行两个正整数减法运算, 234098 -134098703578230056 = -134098703577995958。
*/
#include <stdio.h>
#include <string.h>
void cancel (char s[]);
void reverse (char s[]);

int main()
{
char a[100]={'\0'},b[100]={'\0'},temp[100]={'\0'};
int len_a,len_b;
int i;
gets(a);
gets(b);

//去掉数组前面的0
cancel (a);
cancel (b);

len_a=strlen(a);
len_b=strlen(b);

//使前一个数大于后一个数,并输出负号
if (len_a<len_b || ((len_a==len_b)&&(a[0]<b[0]))){
strcpy(temp,a);
strcpy(a,b);
strcpy(b,temp);
printf ("-");

len_a=strlen (a);
len_b=strlen(b);
}

//颠倒a[],b[]
reverse (a);
reverse (b);

//减法计算
for (i=0;i<len_a;i++)
if (a[i]>=b[i]){
if (b[i]==0)
a[i]=a[i];
else
a[i]=a[i]-b[i]+'0';
}
else{
a[i]=a[i]+10-b[i]+'0';
a[i+1]=a[i+1]-'1';//▲▲▲这一步好像不太对???▲▲▲
}
reverse (a);
cancel (a);

printf ("%s\n",a);
return 0;
}

//删除数组前面的0
void cancel (char s[]){
int len_s,i,j;
len_s=strlen(s);
for (i=0;i<len_s-1;i++)
if (s[i]=='0'){
for (j=i;j<len_s-1;j++)
s[j]=s[j+1];
s[j]='\0';
len_s--;
i--;
}
else
break;
}

//颠倒字符串
void reverse (char s[]){
int i,j,len_s;
char temp;
len_s=strlen(s);
for (i=0,j=len_s-1;i<j;i++,j--){
temp=s[i];
s[i]=s[j];
s[j]=temp;
}
}
...全文
797 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
city_t 2009-08-14
  • 打赏
  • 举报
回复
#include <stdlib.h>
#include <string.h>

void cancel (char s[]);
void reverse (char *,int);

char* minus(char *a,char *b){
int flag=0;
char *temp=a;
while(*b!='\0')
{
if(*a>=*b+flag)
{
*a=*a-*b-flag+'0';
flag=0;
a++;b++;
}
else
{
*a=*b-*a-flag+'0';
flag=1;
a++;b++;
}
}
a=temp+strlen(temp)-1;
while(*a=='0')
a--;
*(a+1)='\0';
return temp;
}


int main()
{
char *a, *b;
a=(char *)malloc(sizeof(char)*100);
b=(char *)malloc(sizeof(char)*100);
gets(a);
gets(b);
int len;

//颠倒a[],b[]
reverse (a,strlen(a));
reverse (b,strlen(b));
//减法计算
if(strcmp(a,b))
{
if(strlen(a)==strlen(b) && *a>*b)
{
a=minus(a,b);
len=strlen(a);
}
else if(strlen(a)>strlen(b))
{
a=minus(a,b);
len=strlen(a);
}
else
{
a=minus(b,a);
len=strlen(a)+1;
*(a+strlen(a))='-';
*(a+strlen(a)+1)='\0';
}
reverse(a,len);
}
else
{
*a='0';
*(a+1)='\0';
}

printf ("%s\n",a);
return 0;
}


//颠倒字符串
void reverse (char *s,int len){
char *temp;
temp=(char *)malloc(sizeof(char)*len);
int i;
for(i=len;i>0;i--)
*temp++=*(s+i-1);
*temp='\0';
temp=temp-len;
while((*(s+(i++))=*temp++)!='\0');

}

只能运算正整数
qzl123666 2009-08-14
  • 打赏
  • 举报
回复
加减法很简单啊,难的是除法,乘法可以用加法来做,我还做过开根号的,有点类似除法
lzy0001sl 2009-08-13
  • 打赏
  • 举报
回复
我写的大数的加减乘除的运算,正确但效率不太好,因为数组的一个元素存的是一个十进制的数,要存10000进制就高得多了。呵呵可惜有点麻烦就没那么做。

#include<stdio.h>
#include <string.h>
#include "time.h"
#define MAX 300

void Add(char *ch1 , char *ch2 , char *ch3) //ch1+ch2=ch3
{
int len1=strlen(ch1);
int len2=strlen(ch2);

for (int q=0; q<len1; q++)//判断输入
{
if (48 <= ch1[q] && ch1[q] <= 57)
continue;
else
{
printf("ch1含有非法字符,你的输入只能是数字\n");
ch3[0] = '\0';
return;
}
}
for (q=0; q<len2; q++)
{
if (48 <= ch2[q] && ch2[q] <= 57)
continue;
else
{
printf("ch2含有非法字符,你的输入只能是数字\n");
ch3[0] = '\0';
return;
}
}

int len3, i, tmp;
int num1[MAX], num2[MAX], num3[MAX];

memset (num1 , 0 , sizeof(num1));
memset (num2 , 0 , sizeof(num2));
memset (num3 , 0 , sizeof(num3));

for (i=len1-1;i>=0;i--)//字符转换为数组
num1[len1-1-i] = ch1[i] - 48;
for (i=len2-1;i>=0;i--)
num2[len2-1-i] = ch2[i] - 48;

i=0;
tmp=0;
len3=len1>len2?len1:len2;

while (i < len3)
{
num3[i] = num1[i] + num2[i] + tmp;
if (num3[i] >= 10)
{
tmp = 1;
num3[i] -= 10;
}else
tmp = 0;
i ++;
}
if(tmp != 0)
{
num3[i] = tmp;
i ++;
}
len3 = i;
for (i=len3-1; i>=0; i--)
ch3[len3-1-i] = num3[i] + 48;

ch3[len3] = '\0';
return ;
}

int cmp(char *ch1 , char *ch2) //比较大小
{
int i , len1 = strlen (ch1) , len2 = strlen (ch2);
if (len1 > len2)
return 1;
if (len2 > len1)
return -1;
for (i=0; i<len1; i++)
{
if (ch1[i] > ch2[i])
return 1;
if (ch1[i] < ch2[i])
return -1;
}
return 0;
}

void Minus(char *ch1 , char *ch2 , char *ch3) //ch1-ch2=ch3
{
int len1=strlen(ch1);
int len2=strlen(ch2);

for (int q=0; q<len1; q++)//判断输入
{
if (48 <= ch1[q] && ch1[q] <= 57)
continue;
else
{
printf("ch1含有非法字符,你的输入只能是数字\n");
ch3[0] = '\0';
return;
}
}
for (q=0; q<len2; q++)
{
if (48 <= ch2[q] && ch2[q] <= 57)
continue;
else
{
printf("ch2含有非法字符,你的输入只能是数字\n");
ch3[0] = '\0';
return;
}
}


int i=0;
int tmp = 0;
int len3;


int num1[MAX], num2[MAX], num3[MAX];

memset (num1 , 0 , sizeof(num1));
memset (num2 , 0 , sizeof(num2));
memset (num3 , 0 , sizeof(num3));

for (i=0; i<len1; i++)
num1[len1-1-i] = ch1[i] - 48;//低地址存低位,高地址存高位
for (i=0; i<len2; i++)
num2[len2-1-i] = ch2[i] - 48;

len3 = len1 > len2 ? len1 : len2;
i=0;

int cm = cmp(ch1, ch2);
if (cm == 1)
{
while (i < len3)
{
num3[i] = num1[i] - num2[i] - tmp;
if (num3[i] < 0)
{
num3[i] += 10;
tmp = 1;
}
else
tmp = 0;
i ++;
}
while ((len3 > 1) && (num3[len3-1] == 0))//去掉最高位的一些0
len3 --;
for (i=0; i<len3; i++) //将整数数组转换为字符串
ch3[i] = num3[len3-1-i] + 48;
ch3[len3] = '\0';
}else if (cm == 0)
{
ch3[0] = '0';
ch3[1] = '\0';
}else if (cm == -1)
{
Minus(ch2, ch1, ch3);//变换参数,调用自身
int le = strlen(ch3);
for (int j=0; j<le; j++)//后移一位
{
ch3[le - j] = ch3[le - j - 1];
}
ch3[0] = '-';
ch3[le + 1] = '\0';//必须加
}

return ;
}


void Div(char *ch1 , char *ch2 , char *ch3) //ch1/ch2=ch3求商
{
clock_t start, end;
printf("I am running! Please wait for a long time!\n");
start = clock();
int len1 = strlen(ch1);
int len2 = strlen(ch2);

for (int q=0; q<len1; q++)//判断输入
{
if (48 <= ch1[q] && ch1[q] <= 57)
continue;
else
{
printf("ch1含有非法字符,你的输入只能是数字\n");
ch3[0] = '\0';
return;
}
}
for (q=0; q<len2; q++)
{
if (48 <= ch2[q] && ch2[q] <= 57)
continue;
else
{
printf("ch2含有非法字符,你的输入只能是数字\n");
ch3[0] = '\0';
return;
}
}

int num1[MAX], num2[MAX], num3[MAX];
int i = 0;

memset(num1 , 0 , sizeof(num1));
memset(num2 , 0 , sizeof(num2));
memset(num3 , 0 , sizeof(num3));
memset(ch3 , 0 , MAX);


for (i=0; i<len1; i++)
{
num1[len1-1-i] = ch1[i] - 48;
}//低地址存低位,高地址存高位
for (i=0; i<len2; i++)
num2[len2-1-i] = ch2[i] - 48;

char ptemp[MAX];
char temp[2] = {0};

while (cmp(ch1, ch2) >= 0)
{
Minus(ch1, ch2, ptemp);
temp[0] = '1';
Add(ch3, temp, ch3);
memcpy(ch1, ptemp, strlen(ptemp) + 1);
memset(ptemp, 0, MAX);
}
end = clock();
double duration = ((double)(end - start))/CLOCKS_PER_SEC;
printf("运行时间为:%f\n", duration);
return ;

}

/*void Mod (char *ch1 , char *ch2) //取于ch1=ch1%ch2求余数
{
int i , len1 , len2 , tmp;
char ch3[MAXCHAR];
while (cmp (ch1 , ch2) >= 0)
{
len1 = strlen (ch1) , len2 = strlen (ch2);
tmp = len1-len2-1 > 0 ? len1-len2-1 : 0;
memcpy (ch3 , ch2 , (len2+1)*sizeof(char));
for (i=0;i<tmp;i++)
ch3[len2+i]='0';
ch3[len2+i]='\0';
Minus (ch1 , ch3 , ch1); //result ch1
}
return ;
}


char*mcd(char*a,char*b)
{
Mod(a,b);
if(a[0]=='0')
return b;
else
return mcd(b,a);
}*/

void Mul(char*ch1, char*ch2, char*ch3)//乘法 a*b=c
{
int len1=strlen(ch1);
int len2=strlen(ch2);
int i = 0;
int j = 0;
int flag = 0;
int offset = 0;

for (int q=0; q<len1; q++)//判断输入
{
if (48 <= ch1[q] && ch1[q] <= 57)
continue;
else
{
printf("ch1含有非法字符,你的输入只能是数字\n");
ch3[0] = '\0';
return;
}
}
for (q=0; q<len2; q++)
{
if (48 <= ch2[q] && ch2[q] <= 57)
continue;
else
{
printf("ch2含有非法字符,你的输入只能是数字\n");
ch3[0] = '\0';
return;
}
}

int num1[MAX], num2[MAX], num3[MAX];

memset (num1 , 0 , sizeof(num1));
memset (num2 , 0 , sizeof(num2));
memset (num3 , 0 , sizeof(num3));

for (i=len1-1;i>=0;i--)//字符转换为数组
num1[len1-1-i] = ch1[i] - 48;
for (i=len2-1;i>=0;i--)
num2[len2-1-i] = ch2[i] - 48;


for (i=0; i<len1; i++)
{
flag = 0;
offset = i;
for (j=0; j<len2; j++)
{
num3[j + offset] += num1[i]*num2[j] + flag;//注意+=
if (num3[j+offset] >= 10)
{
flag = num3[j+offset]/10;//进位
num3[j+offset] = num3[j+offset]%10;
}else
{
flag = 0;
}
}
if (flag != 0)//最高位有可能进位
{
num3[j + offset] = flag;
j++;//为了计算积的长度
}
}

int len3 = j+offset;//
for (i=len3-1; i>=0; i--)
ch3[len3-1-i] = num3[i] + 48;

ch3[len3] = '\0';

}

int main()
{
char s1[MAX];
char s2[MAX];
char output[MAX];
printf("Please input two big INT number!\n");
scanf("%s%s", s1, s2);

Minus(s1, s2, output);
printf("Minus = %s\n", output);

Add(s1, s2, output);
printf("Add = %s\n", output);

Mul(s1, s2, output);
printf("Mul = %s\n", output);

Div(s1, s2, output);

printf("Div = %s\n", output);

return 0;
}
mstlq 2009-08-13
  • 打赏
  • 举报
回复

//使前一个数大于后一个数,并输出负号
if (len_a <len_b || ((len_a==len_b)&&(a[0] <b[0]))){
//这个判断也不够,可能出现len_a==len_b &&a[0] ==b[0] && a[1] ==b[1],
//这种情况也是a表示的数字小于b啊,可惜程序无视了


//减法计算
for (i=0;i <len_a;i++)
if (a[i]>=b[i]){
if (b[i]==0)
a[i]=a[i];
else
a[i]=a[i]-b[i]+'0';
}
else{
a[i]=a[i]+10-b[i]+'0';
a[i+1]=a[i+1]-'1';//这里-'1'应该是-1,另外请考虑a[i+1]也等于‘0’的情况
}
reverse (a);
cancel (a);

printf ("%s\n",a);
return 0;
}
abckangaroo 2009-08-13
  • 打赏
  • 举报
回复

/*
【问题描述】
编写程序实现两个超长正整数(每个最长80位数字)的减法运算。

【输入形式】
从键盘读入两个整数,要考虑输入高位可能为0的情况(如00083)。
1. 第一行是超长正整数A;
2. 第二行是超长正整数B;

【输出形式】
输出只有一行,是长整数A减去长整数B的运算结果,从高到低依次输出各位数字。
要求:若结果为0,则只输出一个0;否则输出的结果的最高位不能为0,并且各位数字紧密输出。
【输入样例】

234098
134098703578230056

【输出样例】
-134098703577995958
【样例说明】
进行两个正整数减法运算, 234098 -134098703578230056 = -134098703577995958。
*/
#include <stdio.h>
#include <string.h>
void cancel (char s[]);
void reverse (char s[]);

int main()
{
char a[100]={'\0'},b[100]={'\0'},temp[100]={'\0'};
int len_a,len_b;
int i;
gets(a);
gets(b);

//去掉数组前面的0
cancel (a);
cancel (b);

len_a=strlen(a);
len_b=strlen(b);

//使前一个数大于后一个数,并输出负号
if (len_a<len_b || ((len_a==len_b)&&(a[0]<b[0]))){
strcpy(temp,a);
strcpy(a,b);
strcpy(b,temp);
printf ("-");

len_a=strlen (a);
len_b=strlen(b);
}

//颠倒a[],b[]
reverse (a);
reverse (b);

//减法计算
for (i=0;i<len_a;i++)
if (a[i]>=b[i]){
if (b[i]==0)
a[i]=a[i];
else
a[i]=a[i]-b[i]+'0';
}
else{
a[i]=a[i]+10-b[i]+'0';
a[i+1]=a[i+1]-'1';
}
reverse (a);
cancel (a);

printf ("%s\n",a);
return 0;
}

//删除数组前面的0
void cancel (char s[]){
int len_s,i,j;
len_s=strlen(s);
for (i=0;i<len_s-1;i++)
if (s[i]=='0'){
for (j=i;j<len_s-1;j++)
s[j]=s[j+1];
s[j]='\0';
len_s--;
i--;
}
else
break;
}

//颠倒字符串
void reverse (char s[]){
int i,j,len_s;
char temp;
len_s=strlen(s);
for (i=0,j=len_s-1;i<j;i++,j--){
temp=s[i];
s[i]=s[j];
s[j]=temp;
}
}

69,382

社区成员

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

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