[模板]大整数相加、相乘

欢迎测试!

/*
    大整数 C 模版 (大整数相加,相乘) 
    字符串形式输入,s[0]为最高位
    
    author : http://www.cnblogs.com/JMDWQ/
*/

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

# define MAXN (10000 + 5)                   /* MAXN -- 输入中整数的最大位数 */

char a[MAXN], b[MAXN], c[2 * MAXN];

 int    bign_prep(char *s);
void    str_rev(char *s);
 int    bign_cmp(char *a, char *b);
void    Add(char *a, char *b, char *c);
 int    Sub(char *a, char *b, char *c);
void    Mul(char *a, char *b, char *c);
void    cal(char *a, char *b, char *c, char op);

int main()
{
    char opd[5];
    while (~scanf("%s%s%s", a, opd, b))
        cal(a, b, c, opd[0]);
    
    return 0;
}

/* 处理大整数前的负号,并返回大整数的符号 */
int bign_prep(char *s)
{
    int i;
    if (s[0] != '-')
    {
        for (i = 0; s[i]; ++i)
            if (s[i] != '0') return 1;
        return 0;
    }
    for (i = 0; s[i]; ++i)
        s[i] = s[i+1];
    return -1;
}

/* 字符串反转,s 末尾必须是 '\0' */
void str_rev(char *s)
{
    char ch;
    int i, n, len = strlen(s);
    n = len >> 1;
    for (i = 0; i < n; ++i)
        ch = s[i], s[i] = s[len-1-i], s[len-1-i] = ch;
}
/* 两个无符号大整数相比较, 返回 a-b 的符号,a==b 时返回 0 */
int bign_cmp(char *a, char *b)
{
    int i, lenx = strlen(a), leny = strlen(b);
    if (lenx > leny) return 1;
    if (lenx < leny) return -1;
    for (i = 0; i < lenx; ++i)
        if (a[i] > b[i])
            return 1;
        else if (a[i] < b[i])
            return -1;
    return 0;
}

/* 无符号大整数相加, c = a+b */
void Add(char *a, char *b, char *c)
{
    int i, tmp, ea = 1, eb = 1, carry = 0;
    str_rev(a), str_rev(b);
    for (i = 0; a[i]||b[i]; ++i)
    {
        if (!a[i]) ea = 0;
        if (!b[i]) eb = 0;
        tmp = carry;
        if (ea) tmp += a[i]-'0';
        if (eb) tmp += b[i]-'0';
        c[i]  = tmp % 10 + '0';
        carry = tmp / 10;
    }
    if (carry) c[i++] = carry+'0';
    while (--i && c[i] == '0') ;
    c[i+1] = '\0';
    str_rev(a), str_rev(b), str_rev(c);
}

/* c = abs(a-b), 返回 a-b 的符号, a==b时返回0,此时 c == "0" */
int Sub(char *a, char *b, char *c)
{
    char *p, *q;
    int i, n, tmp, sgnc, eq = 1, carry = 0;
    sgnc = bign_cmp(a, b);
    if (sgnc == 0) {c[0] = '0', c[1] = '\0'; return 0;}
    else if (sgnc > 0) p = a,q = b;
    else p = b, q = a;
    str_rev(a), str_rev(b);
    for (i = 0; p[i]||q[i]; ++i)
    {
        tmp = p[i]-'0'-carry;
        if (!q[i]) eq = 0;
        if (eq) tmp -= (q[i]-'0');
        if (tmp < 0) carry = 1;
        else carry = 0;
        c[i] = (tmp+10)%10+'0';
    }
    while (--i && c[i] == '0') ;
    c[i+1] = '\0';
    str_rev(a), str_rev(b), str_rev(c);
    return sgnc;
}
/* 无符号大整数相乘 */
void Mul(char *a, char *b, char *c)
{
    int i, j, tmp, lenx = strlen(a), leny = strlen(b);
    str_rev(a), str_rev(b);
    memset(c, 0, sizeof(char)*(lenx+leny));
    for (i = 0; a[i]; ++i)
    for (j = 0; b[j]; ++j)
    {
        tmp = c[i+j]+(a[i]-'0')*(b[j]-'0');
        c[i+j+1] += tmp/10;
        c[i+j] = tmp%10;
    }
    for (i = lenx+leny-1; !c[i]; --i) ;
    c[i+1] = '\0';
    for (; i >= 0; --i) c[i] += '0';
    str_rev(a), str_rev(b), str_rev(c);
}
/* 模拟大数计算器(加法和乘法),直接输出计算结果 */
void cal(char *a, char *b, char *c, char op)
{
    int op_sgn, sgna, sgnb, sub_sgn;
    sgna = bign_prep(a);
    sgnb = bign_prep(b);
    if (op == '+' || op == '-')
    {
        op_sgn = (op=='-' ? -1:1);
        if (op_sgn*sgna*sgnb > 0)
        {
            Add(a, b, c);
            if (sgna < 0) putchar('-');
            puts(c);
        }
        else
        {
            sub_sgn = Sub(a, b, c);
            if (sub_sgn*sgna < 0) putchar('-');
            puts(c);
        }
    }
    else if (op == '*')
    {
        Mul(a, b, c);
        if (sgna*sgnb < 0) putchar('-');
        puts(c);
    }
}

 使用long long测的,测试程序

下面的没包含负号,整数前包含负号的情况测过了,这个是之前的数据。

/*************************sample**************************/

input

=====

1 - 2
45 - 2
100 - 100
1000 - 1000
1000 - 10000
999 - 999999
1 + 2
45 + 2
100 + 100
1000 + 1000
1000 + 10000
999 + 999999
1 * 2
45 * 2
100 * 100
1000 * 1000
1000 * 10000
999 * 999999

=====

output

=====
-1
43
0
0
-9000
-999000
3
47
200
2000
11000
1000998
2
90
10000
1000000
10000000
998999001

=====
Used: 10 ms, 1448 KB

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

posted on 2012-08-09 16:46  getgoing  阅读(949)  评论(0编辑  收藏  举报

导航