[UVa] 465 - Overflow

破水题,耗我精力,颓我精神。。。
按照《算法入门经典》的题目列表来做,前几题用到了高精度,所以这一题打算直接用高精度计算,几分钟水过去。没想到一水就是几个小时。最后终于在百度了好多博客之后,找到了自己的bug。
0000000000000001 + 0000000000000001 这样的数据我是过不去的,字符串转换为高精度数的时候我忘记清除前导0了。

题目:

 
Write a program that reads an expression consisting of two non-negative integer and an operator.
Determine if either integer or the result of the expression is too large to be represented as a “normal”
signed integer (type integer if you are working Pascal, type int if you are working in C).

Input

An unspecified number of lines. Each line will contain an integer, one of the two operators ‘+’ or ‘*’,
and another integer.

Output

For each line of input, print the input followed by 0-3 lines containing as many of these three messages
as are appropriate: ‘first number too big’, ‘second number too big’, ‘result too big’.

Sample Input

300 + 3
9999999999999999999999 + 11

Sample Output

300 + 3
9999999999999999999999 + 11
first number too big
result too big

题目大意就是输入两个数和一个操作符,判断这两个数和计算结果是否超过int的最大值。

我的代码没什么技巧,也不值得别人参考,就是为了再熟悉一下高精度计算才这么写。
果然找到了一个致命的bug。我的高精度还得再完善。
代码:

#include<stdio.h>
#include<string.h>
#define MAXN 10001

const int base = 10000;
const int digit = 4;
typedef int bignum[MAXN];

char str1[MAXN], str2[MAXN], c;
bignum num1, num2, ans;

void str2num(char *str, bignum num);
void printBIgnum(bignum num);
void add(bignum num1, bignum num2, bignum ans);
void mul(bignum num1, bignum num2, bignum ans);
int isOverflow_int(bignum num);

int main()
{
    memset(str1, 0, sizeof(str1));
    memset(str2, 0, sizeof(str2));
    while(scanf("%s %c %s", str1, &c, str2) == 3)
    {
        printf("%s %c %s\n", str1, c, str2);
        str2num(str1, num1);
        str2num(str2, num2);
        if(isOverflow_int(num1)) printf("first number too big\n");
        if(isOverflow_int(num2)) printf("second number too big\n");
        if(c == '+') add(num1, num2, ans);
        else mul(num1, num2, ans);
        if(isOverflow_int(ans)) printf("result too big\n");

        memset(str1, 0, sizeof(str1));
        memset(str2, 0, sizeof(str2));
    }
    return 0;
}

void str2num(char *str, bignum num)
{
    memset(num, 0, sizeof(bignum));
    *num = 0;
    int len = strlen(str);
    while(len > 0)
    {
        int d = len > digit ? digit : len;
        int i, n = 0, w = 1;
        for(i = 0; i < d; i++)
        {
            n += (str[len-1-i] - '0') * w;
            w *= 10;
        }
        num[++*num] = n;
        len -= d;
    }
    while(!num[*num] && *num > 0) --*num;
}

void printBIgnum(bignum num)
{
    printf("%d", num[*num]);
    int i;
    for(i = *num - 1; i > 0; i--) printf("%04d", num[i]);
    printf("\n");
}

void add(bignum num1, bignum num2, bignum ans)
{
    memset(ans, 0, sizeof(bignum));
    *ans = *num1 > *num2 ? *num1 : *num2;
    int pos, carry = 0;
    for(pos = 1; pos <= *ans; pos++)
    {
        carry += num1[pos] + num2[pos];
        ans[pos] = carry % base;
        carry /= base;
    }
    while(carry)
    {
        ans[++*ans] = carry % base;
        carry /= base;
    }
}

void mul(bignum num1, bignum num2, bignum ans)
{
    memset(ans, 0, sizeof(bignum));
    int i, j, carry = 0;
    for(j = 1; j <= *num2; j++)
    {
        for(i = 1; i <= *num1; i++)
        {
            ans[i+j-1] += num1[i] * num2[j] + carry;
            carry = ans[i+j-1] / base;
            ans[i+j-1] %= base;
        }
        i = *num1 + j;
        while(carry)
        {
            ans[i++] = carry % base;
            carry /= base;
        }
    }
    *ans = *num1 + *num2;
    while(!ans[*ans] && *ans > 0) --*ans;
}

int isOverflow_int(bignum num)
{
    /*2147483647*/
    if(*num < 3) return 0;
    else if(*num > 3 || num[3] > 21) return 1;
    else if(num[3] < 21) return 0;
    else if(num[2] > 4748) return 1;
    else if(num[2] < 4748) return 0;
    else if(num[1] > 3647) return 1;
    else return 0; 
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值