NOJ 1149高精度乘法(另含高精度加、减&除详解)

#include <iostream>
using namespace std;

const long MAXN = 100000;

inline long& len(long* a)
{
 return a[MAXN-1];
}

void copy(long* to, long* scr)
{
 len(to) = len(scr);
 memcpy(to,scr,sizeof(long)*len(to)); 
}

void change(char* s,long l, long* a)//l是s的长度
{
 long i,j(0),cnt(0),k;

 if (l <= 4)
 {
  for (i=0; i<l; i++)
   j = j*10 + s[i] - '0';
  a[len(a)++] = j;
 } 
 else
 {
  for (i=l-4; i<l; i++)
   j = j*10 + s[i] - '0';
  a[len(a)++] = j;
  s[l-4] = '/0'; //截断刚才的4位
  change(s, l-4, a);
 }
}

void cheng(long* a, long* b, long* c)
{
 long i,j;
 len(c) = len(a) + len(b);
 memset(c,0,sizeof(long)*len(c));
 
 for (i=0; i<len(a); i++)
  for (j=0; j<len(b); j++)
  {
   c[i+j] += a[i] * b[j];
   c[i+j+1] += c[i+j] / 10000;
   c[i+j] %= 10000;
  }
 while(len(c) > 1 && c[len(c)-1] == 0) len(c)--;
}
void print(long* a)
{
 long i;
 printf("%ld",a[len(a)-1]);
 
 for (i=len(a)-2; i>=0; i--)
  printf("%04ld",a[i]);
 printf("/n");
}

int main(void)
{
 long i,n,a[MAXN],b[MAXN],c[MAXN];
 char s[10000];

 while(scanf("%s",s) == 1)
 {
  len(a) = 0;//需要这样
  change(s,strlen(s),a);
  while(len(a) > 1 && a[len(a)-1] == 0) len(a)--; //去前导零
  
  scanf("%s",s); len(b) = 0;
  change(s,strlen(s),b);
  
  cheng(a,b,c);
  
  print(c);
 }
 return 0;
}

o 下面是一个类似于strlen()的函数,在这个高精度计算的过程中都要用到~
o const long MAXN = 100000;//一个很大的数
o inline long& len(long* a)
o {
o return a[MAXN-1];
o }

o 为什么返回一个引用,是为了可以存在如下语句len(a) = 0; len(a)++;等等.
o 其实本质上写这个函数的目的是少用一个len变量,一个数组就要对应一个len变量,要么用struct,么用很多len变量.这两者都挺麻烦的,所以就想到搞了这么一个函数.
o 当然,绝对不是说不能用struct,不能用别的变量记录长度.
 
o void change(char* s, long* a)
o {
o long i,j;
o len(a) = strlen(s);
o memset(a,0,sizeof(long)*len(a));
o for (i=0,j=len(a)-1; i<len(a); i++,j--)
o a[j] = s[i] - '0';
o while(len(a) > 1 && a[len(a)-1] == 0) len(a)--;( 把高位的0出去?我的标注)
o }
o 将字符串s转换成long数组a,红色的字可以将s串倒置存入a数组
 
o void print(long* a)
o {
o long i;
o for (i=len(a)-1; i>=0; i--)
o printf("%ld",a[i]);
o printf("/n");
o }
o print()函数用于输出一个a数组,也就是打印一个高精度,注意要反过来打印~
 
o void copy(long* to, long* scr)
o {
o len(to) = len(scr);
o memcpy(to,scr,sizeof(long)*len(to));
o }
o
 
o void jia(long* a, long* b, long* c)//实现c = a + b
o {
o long i,j = max(len(a), len(b));
o
o if (c == a)// 为了实现a = a + b
o {
o for (i=len(c); i<len(b)+1; i++)// 必要的清零
o c[i] = 0;
o len(c) = j + 1;
o }
o else if (c == b)// 为了实现 b = a + b
{
o jia(b,a,c);// J
return;//!!!!!!
}
用于将scr()复制到to(目标).
 
o else
o {
o memset(c,0,sizeof(long)*(j+1));
o copy(c,a);
o len(c) = j + 1;
o }
o
o for (i=0; i<len(b); i++)
o {
o c[i] += b[i];
o c[i+1] += c[i] / 10;
o c[i] %= 10;
o }
o for (i=len(b); i<j; i++)// 处理没有处理到的进位问题
o {
o c[i+1] += c[i] / 10;
o c[i] %= 10;
o }
o
o while(len(c) > 1 && c[len(c)-1] == 0) len(c)--;
o }
 
o c[i+1] += c[i] / 10;
o c[i] %= 10;
o 这两句解决了进位的问题,而且对进不进都适用.一般的,如果把其中的10换成n的话,就是一个n制的加法(还需要改一下print函数)对后面的减法,乘法同样适用.
o while(len(c) > 1 && c[len(c)-1] == 0) len(c)--;
o 这句话的作用是去除前导零(如果是0除外)
 
o 这里为了方便起见,a赋值给c,然后在c的基础上加上b.
o 注意,这样操作,不管c == a,还是c != a,都是正确的.想想是为什么?~
o 还有,c == b,用了递归调用,其实也很好理解~
o
下面是减法的代码:
 
o void jian(long* a, long* b, long* c) //c = a - b, 需要a >= b
o {
o long i;
o len(c) = len(a); // 因为规定了a >= b
o if (c != a) copy(c,a);
o
o for (i=0; i<len(c); i++)
o {
o c[i] -= b[i];
o if (c[i] < 0)
o {
o c[i] += 10;
o c[i+1] -= 1;
o }
o }
o while(len(c) > 1 && c[len(c)-1] == 0) len(c)--;
o
乘法代码:
 
o void cheng(long* a, long* b, long* c)// c = a * b
o {
o long i,j;
o len(c) = len(a) + len(b);
o memset(c,0,sizeof(long)*len(c));
o
o for (i=0; i<len(a); i++)
o for (j=0; j<len(b); j++)
o {
o c[i+j] += a[i] * b[j];
o c[i+j+1] += c[i+j] / 10;
o c[i+j] %= 10;
o }
o while(len(c) > 1 && c[len(c)-1] == 0) len(c)--;
o }
除法:
 
o void chu(long* a, long*b, long* c)//c = a / b
o {
o long *p = (long*)malloc(sizeof(long)*MAXN),
o *q = (long*)malloc(sizeof(long)*MAXN),
o *ten = (long*)malloc(sizeof(long)*MAXN),
o *tmp = (long*)malloc(sizeof(long)*MAXN),i,cnt;
o
o change("0",p); len(q) = 1; change("10",ten);
o len(c) = len(a);
o memset(c,0,sizeof(long)*len(c));
 
o for (i=len(a)-1; i>=0; i--)
o {
o q[0] = a[i];
o copy(tmp,p); cheng(tmp,ten,p);// p = p * 10
o jia(p,q,p);// p = p + q
o
o cnt = 0;
o while(!xiao(p,b))// 用减法试商的过程
o {
o jian(p,b,p);
o cnt++;
o }
o c[i] = cnt;
o }
o while(len(c) > 1 && c[len(c)-1] == 0) len(c)--;
o
o free(p); free(q); free(tmp); free(ten);//:-)
o }
}
如果能保证a,b无用的数据都是0的话(譬如是全局变量),那么处理多余进位问题的那个循环可以省.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值