天天看點

UVA 465 Overflow 高精度加法和乘法運算

題目給出多組資料,判斷輸入的兩個數是否超出 int 型變量的取值範圍,并判斷最終計算結果是否超出 int 取值範圍

這裡先給出我自己最初寫的AC代碼:

思路:

用兩個string來儲存輸入的數,将他們與 int 的最大值比較大小,然後求出他們的和或者是積來判斷其與int最大值的大小關系

Result  :  Accepted   Memory  :  0 KB   Time  :  15 ms

/*
 * Author: Gatevin
 * Created Time:  2014/7/3 16:54:43
 * File Name: test.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

string s1,s2,ans;

bool check(string s)//判斷其與int最大值的關系
{
    bool zero = true;
    for(int i = 0; i < s.length(); i++)//找到s的起始位,以為之前加法和乘法運算有将s反向過,現在反向回來會有前導零
    {
        if(s[i] != '0')
        {
            zero = false;
            break;
        }
    }
    if(zero) return false;//如果zero = 0,則說明 s = "0"
    int flags = 0;
    for(int i = 0; i < s.length(); i++)
    {
        if(s[i] != '0')
        {
            flags = i;
            break;
        }
    }
    int lens = s.length() - flags;
    string tmp;
    if(sizeof(int)*8 == 32)
    {
        tmp = "2147483647";
    }
    else
    {
        tmp = "32767";
    }
    int lenm = tmp.length();
    if(lens > lenm)
    {
        return true;
    }
    if(lens < lenm)
    {
        return false;
    }
    for(int i = flags, j = 0; i <= s.length() - 1 && j <= tmp.length() - 1; i++,j++)
    {
        if(s[i] > tmp[j])
        {
            return true;
        }
        if(s[i] < tmp[j])
        {
            return false;
        }
    }
    return false;
}

void judge(string ss1, string ss2, char op)
{
    bool res;
    if(op == '*')
    {
        string ans(ss1.length() + ss2.length() + 1, '0');//乘法運算
        reverse(ss1.begin(), ss1.end());
        reverse(ss2.begin(), ss2.end());
        int c;
        for(int i = 0; i < ss1.length(); i++)
        {
            c = 0;
            for(int j = 0; j < ss2.length(); j++)
            {
                /*
                 * 理由參照 剛寫的 UVA 10106 的題解
                 */
                int tmp1 = ((ans[i + j] - '0') + c + (ss1[i] - '0')*(ss2[j] - '0')) /10;
                int tmp2 = ((ans[i + j] - '0') + c + (ss1[i] - '0')*(ss2[j] - '0')) % 10;
                ans[i + j] = tmp2 + '0';
                c = tmp1;
            }
            ans[i + ss2.length()] += c;
        }
        reverse(ans.begin(), ans.end());
        res = check(ans);
    }
    else
    {
        string ans(max(ss1.length(), ss2.length()) + 1,'0');
        reverse(ss1.begin(), ss1.end());
        reverse(ss2.begin(), ss2.end());
        int c = 0;
        if(ss1.length() >= ss2.length())//模拟加法
        {
            for(int i = 0; i < ss2.length(); i++)
            {
                ans[i] = (ss1[i] - '0' + ss2[i] - '0' + c) % 10 + '0';
                c =  (ss1[i] - '0' + ss2[i] - '0' + c) / 10;
            }
            for(int j = ss2.length(); j < ss1.length(); j++)
            {
                ans[j] = (ss1[j] - '0' + c) % 10 + '0';
                c = (ss1[j] - '0' + c) /10;
            }
            ans[ss1.length()] += c;//小心最後的進位
        }
        else
        {
            for(int i = 0; i < ss1.length(); i++)
            {
                ans[i] = (ss2[i] - '0' + ss1[i] - '0' + c) % 10 + '0';
                c =  (ss2[i] - '0' + ss1[i] - '0' + c) / 10;
            }
            for(int j = ss1.length(); j < ss2.length(); j++)
            {
                ans[j] = (ss2[j] - '0' + c) % 10 + '0';
                c = (ss2[j] - '0' + c) /10;
            }
            ans[ss2.length()] += c;
        }
        reverse(ans.begin(), ans.end());
        res = check(ans);
    }
    if(res)
    {
        cout<<"result too big"<<endl;
    }
}

int main()
{
    char mid;
    while(cin>>s1>>mid>>s2)
    {
        bool c1 = check(s1);
        bool c2 = check(s2);
        cout<<s1<<" "<<mid<<" "<<s2<<endl;
        if(c1)
        {
            cout<<"first number too big"<<endl;
        }
        if(c2)
        {
            cout<<"second number too big"<<endl;
        }
        judge(s1,s2,mid);
    }
    return 0;
}
           

然後是套用模闆寫的代碼:

Result  : Accepted    Memory  : 0 KB   Time  :  15 ms

/*
 * Author: Gatevin
 * Created Time:  2014/7/4 12:58:26
 * File Name: test.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

struct bign
{
    int len,s[1000];
    bign()
    {
        len = 0;
        memset(s, 0 ,sizeof(s));
    }
    
    bign operator = (const char* num)
    {
        len = strlen(num);
        for(int i = 0; i < len; i++)
        {
            s[i] = num[len - i - 1] - '0';
        }
        return *this;
    }
    
    bign operator = (int num)
    {
        char s[1000];
        sprintf(s, "%d", num);
        *this = s;
        return *this;
    }
    
    bign(int num)
    {
        *this = num;
    }
    
    bign(const char* num)
    {
        *this = num;
    }
    
    string str() const
    {
        string res = "";
        for(int i = 0; i < len; i++)
        {
            res = (char)(s[i] + '0') + res;
        }
        if(res == "")
        {
            res = "0";
        }
        return res;
    }
    
    bign operator + (const bign& b) const
    {
        bign c;
        c.len = 0;
        for(int i = 0, g = 0; g || i < max(len, b.len); i++)
        {
            int x = g;
            if(i < len) x += s[i];
            if(i < b.len) x += b.s[i];
            c.s[c.len++] = x % 10;
            g = x / 10;
        }
        return c;
    }
    
    bign operator * (const bign& b) const
    {
        bign c;
        c.len = len + b.len;
        int k;
        for(int i = 0; i < len; i++)
        {
            k = 0;
            for(int j = 0; j < b.len; j++)
            {
                int tmp1 = (s[i] * b.s[j] + k + c.s[i + j]) / 10;
                int tmp2 = (s[i] * b.s[j] + k + c.s[i + j]) % 10;
                c.s[i + j] = tmp2;
                k = tmp1;
            }
            c.s[i + b.len] += k;
        }
        while(c.len > 1)
        {
            if(c.s[c.len - 1] == 0)
            {
                c.len--;
            }
            else
            {
                break;
            }
        }
        return c;
    }

    bign operator += (const bign& b)
    {
        *this = *this + b;
        return *this;
    }
    
    bool operator < (const bign& b) const
    {
        if(len != b.len) return len < b.len;
        for(int i = len - 1; i >= 0; i--)
        {
            if(s[i] != b.s[i])
            {
                return s[i] < b.s[i];
            }
        }
        return false;
    }
};


    istream& operator >> (istream &in, bign & x)
    {
        string s;
        in >> s;
        x = s.c_str();
        return in;
    }
    
    ostream& operator << (ostream & out, const bign& x)
    {
        out << x.str();
        return out;
    }


int main()
{
    bign x1,x2;
    char op;
    bign max_int = (1 << (sizeof(int)*8 - 1)) - 1;
   while(cin>>x1>>op>>x2)
   {
       cout<<x1<<" "<<op<<" "<<x2<<endl;
       
       while(x1.len > 1)//處理資料輸入可能是有前導零的情況
       {
           if(x1.s[x1.len - 1] == 0)
           {
               x1.len--;
           }
           else
           {
               break;
           }
       }
       
       while(x2.len > 1)
       {
           if(x2.s[x2.len - 1] == 0)
           {
               x2.len--;
           }
           else
           {
               break;
           }
       }
       
       if(max_int < x1)
       {
           cout<<"first number too big"<<endl;
       }
       if(max_int < x2)
       {
           cout<<"second number too big"<<endl;
       }
       if(op == '+')
       {
           if(max_int < x1 + x2)
           {
               cout<<"result too big"<<endl;
           }
       }
       if(op == '*')
       {
           if(max_int < x1*x2)
           {
               cout<<"result too big"<<endl;
           }
       }
   }
   return 0;
}