zoukankan      html  css  js  c++  java
  • 大数计算器

    //设计一个支持大数运算的计算器,其中乘法使用分治法求解。该计算器支持加减乘除还有开方根运算。
    #include <iostream>
    #include <list>
    #include <string>
    #include <cstdio>
    #include <cctype>
    #include <cmath>
    using namespace std;
    list<char> Add(list<char> s, list<char> t);
    list<char> Sub(list<char> s, list<char> t);
    list<char> Mul(list<char> s, list<char> t);
    void Div(list<char> s, list<char> t);
    void  Root(list<char>);
    void print(list<char> ans);
    void printhelp()             //打印帮助信息
    {
        cout << "请选择要进行的大数运算" << endl;
        cout << "1:加法运算" << endl;
        cout << "2:减法运算" << endl;
        cout << "3:乘法运算" << endl;
        cout << "4:除法运算" << endl;
        cout << "5:开平方根运算" << endl;
        cout << "6:退出" << endl;
    }
    list<char> Add(list<char> num1,list<char> num2)  //加法运算
    {
        list<char> ans;
        list<char>::iterator iter1,iter2;
        iter1 = num1.begin();
        iter2 = num2.begin();
        int sign = 0;                                   //标记结果符号
        if((*iter1) == '-' && (*iter2) == '-')        //如果两个数都是负数
        {
            num1.pop_front();
            num2.pop_front();
            sign = 1;
            ans = Add(num1,num2);
            ans.push_front('-');
        }
        else if((*iter1) == '-' && (*iter2) != '-')      //如果一负一正
        {
            num1.pop_front();
            ans = Sub(num2,num1);
    
        }
        else if((*iter1) != '-' && (*iter2) == '-')      //如果一正一负
        {
            num2.pop_front();
            ans = Sub(num1,num2);
        }
        else                                          //如果都为正
        {
            int len1,len2,i,len,carry;
            len1 = num1.size();
            len2 = num2.size();
            if(len1 >= len2)                     //补齐两个数的位数
            {
                len = len1;
                for(i = 0; i < len1 - len2; i++)
                    num2.push_front('0');
            }
            else
            {
                len = len2;
                for(i = 0; i < len2 - len1; i++)
                    num1.push_front('0');
            }
            //print(num1);
            //print(num2);
            carry = 0;
            iter1 = num1.end();
            iter2 = num2.end();
            iter1--;
            iter2--;
            for(;(iter1 != num1.begin()) && (iter2 != num2.begin()); --iter1,--iter2)  //进行运算
            {
                i = (*iter1 - '0') + (*iter2 - '0') + carry;
                //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl;
                ans.push_front((i % 10) + '0');
                carry = i / 10;
            }
            i = (*iter1 - '0') + (*iter2 - '0') + carry;
            //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl;
            ans.push_front((i % 10) + '0');
            carry = i / 10;
            if(carry)
                ans.push_front(carry+'0');
        }
        return ans;                                                     //返回结果
    }
    list<char> Sub(list<char> num1,list<char> num2)                    //减法运算
    {
        list<char> ans;
        int sign = 0;
        list<char>::iterator iter1,iter2;
        int len1,len2,len;
        iter1 = num1.begin();
        iter2 = num2.begin();
        if((*iter1) == '-' && (*iter2) == '-')                  //如果两个数都为负数
        {
            num2.pop_front();
            num1.pop_front();
            ans = Sub(num2,num1);
            //ans.push_front('-');
        }
        else if( (*iter1) == '-' && (*iter2) != '-')              //如果一负一正
        {
            num1.pop_front();
            ans = Add(num1,num2);
            ans.push_front('-');
        }
        else if( (*iter1) != '-' && (*iter2) == '-')              //如果一正一负
        {
            num2.pop_front();
            ans = Add(num1,num2);
    
        }
        else                                                   //如果都为正
        {
            len1 = num1.size();
            len2 = num2.size();
            if(len1 >= len2)                                 //补齐位数
            {
                len = len1;
                for(int i = 0; i < len1 - len2; i++)
                    num2.push_front('0');
            }
            else
            {
                len = len2;
                for(int i = 0; i < len2 - len1; i++)
                    num1.push_front('0');
            }
            //print(num1);cout << endl;
            //print(num2);cout << endl;
            int carry = 0,i;
            iter1 = num1.end();
            iter2 = num2.end();
            iter1--;
            iter2--;
            for(;(iter1 != num1.begin()) && (iter2 != num2.begin()); --iter1,--iter2)    //进行运算
            {
                i = (*iter1 - '0' - carry) - (*iter2 - '0');
                carry = 0;
                if( i < 0)
                {
                    i += 10;
                    carry = 1;
                }
                //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl;
                ans.push_front((i % 10) + '0');
            }
            i = (*iter1 - '0' - carry) - (*iter2 - '0');
            if(i < 0)
            {
                i += 10;
                sign = 1;
            }
            //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl;
            if(i) ans.push_front(i + '0');
            if(sign)
                ans.push_front('-');
        }
        return ans;
    }
    list<char> Mul(list<char> num1,list<char> num2)  // 分治法求两大数的积
    {
        list<char> ans;
        int sign = 0;
        int len1,len2,len;
        list<char>::iterator iter1,iter2,iter;
        list<char> high,low;
        list<char> anshigh,anslow;
        int th,tl;
        int i,j,k;
        //print(num1);cout << endl;
        //print(num2);cout << endl;
        if(num1.size() == 1 && num2.size() == 1)     //如果两数都已是一位数,则进行运算
        {
            th = *(num1.begin()) - '0';
            tl = *(num2.begin()) - '0';
            th *= tl;
            ans.push_front( th % 10 + '0');
            ans.push_front( th / 10 + '0');
            return ans;
        }
        else if(num1.size() == 1 && num2.size() > 1)            //如果num1位数大于1,则对Num1分治求积
        {
             if(*(num2.begin()) == '-')
               {
                    sign = 1;
                    num2.pop_front();
               }
             len2 = num2.size();
             if(len2 == 1)
             {
                ans = Mul(num1,num2);
                if(sign)
                    ans.push_front('-');
             }
             else
             {
                for(iter= num2.begin(),i = 0; i < len2 / 2; i++,iter++)
                {
                    high.push_back(*iter);
                }
                for(;iter!=num2.end();iter++)
                {
                    low.push_back(*iter);
                }
                len = low.size();
                anshigh = Mul(num1,high);                 //num1分为两部分,high,low
                anslow = Mul(num1,low);
                for(i = 0; i < len; i++)
                    anshigh.push_back('0');
                ans = Add(anshigh,anslow);                 //合并结果
                if(sign)
                    ans.push_front('-');
             }
             return ans;
        }
        else if(num2.size() == 1 && num1.size() > 1)              //如果num2位数大于1,则对Num2分治求积
        {
             if(*(num1.begin()) == '-')
               {
                    sign = 1;
                    num1.pop_front();
               }
             len1 = num1.size();
             if(len2 == 1)
             {
                ans = Mul(num1,num2);
                if(sign)
                    ans.push_front('-');
             }
             else
             {
                for(iter= num1.begin(),i = 0; i < len1 / 2; i++,iter++)
                {
                    high.push_back(*iter);
                }
                for(;iter!=num1.end();iter++)
                {
                    low.push_back(*iter);
                }
                len = low.size();
                anshigh = Mul(num2,high);                   //num2分为两部分,high,low
                anslow = Mul(num2,low);
                for(i = 0; i < len; i++)
                    anshigh.push_back('0');
                ans = Add(anshigh,anslow);                    //合并结果
                if(sign)
                    ans.push_front('-');
             }
             return ans;
        }                                                       //如果两数位数都大于1,则都运用分治
        else
        {
            list<char> num1high,num1low,num2high,num2low;
            int flag1 = 0,flag2 = 0;
            if(*(num1.begin()) == '-')
            {
                flag1 = 1;
                num1.pop_front();
            }
            if(*(num2.begin()) == '-')
            {
                flag2 = 1;
                num2.pop_front();
            }
            if((flag1 == 1 && flag2 == 0)||(flag1 == 0 && flag2 == 1))  //如果有一正一负,则标记结果为负
            {
                sign = 1;
            }
            len1 = num1.size();
            len2 = num2.size();
            if(len1 == 1 || len2 == 1)                 //如果有一个数是一位数,则直接递归调用
            {
                ans = Mul(num1,num2);
                if(sign)
                    ans.push_front('-');
            }
            else
            {                                                //否则分治法求
                for(iter = num1.begin(),i = 0; i < len1 / 2; iter++,i++)
                    num1high.push_back(*iter);            //被乘数高位部分
                for( ; iter != num1.end(); iter++)
                    num1low.push_back(*iter);                 //被乘数低位部分
                for(iter = num2.begin(),i = 0; i < len2 / 2; iter++,i++)
                    num2high.push_back(*iter);                  //乘数高位部分
                for( ; iter != num2.end(); iter++)
                    num2low.push_back(*iter);                    //乘数低位部分
                int a = (len1 + 1) / 2;
                int b = (len2 + 1) / 2;
                list<char> AC,AD,BC,BD;
                //print(num2high);cout << endl;
                //print(num2low);cout << endl;
                AC = Mul(num1high,num2high);                  //运用X=A*10^a + B; Y= C*10^b + D;
                AD = Mul(num1high,num2low);                   // X*Y = AC * 10 ^(a+b) + AD *10^a + BC * 10 ^b + BD公式求
                BC = Mul(num1low,num2high);
                BD = Mul(num1low,num2low);
                for(i = 0; i < a + b; i++)
                    AC.push_back('0');
                for(i = 0; i < a; i++)
                    AD.push_back('0');
                for(i = 0; i < b; i++)
                    BC.push_back('0');
                ans = Add(AC,AD);
                ans = Add(ans,BC);
                ans = Add(ans,BD);                            //累加结果
                if(sign)
                    ans.push_front('-');
            }
            return ans;
        }
    }
    void Div(list<char> num1,list<char> num2)                 //用辗转相除求结果
    {
        list<char> ans;
        list<char> temp;
        int len1,len2,len;
        int i,j,k;
        int sign = 0;
        int flag1 = 0,flag2 = 0;
        list<char>::iterator iter;
        if(*(num1.begin()) == '-')
        {
            flag1 = 1;
            num1.pop_front();
        }
        if(*(num2.begin()) == '-')
        {
            flag2 = 1;
            num2.pop_front();
        }
        if((flag1 == 1 && flag2 != 1) || (flag1 == 0 && flag2 == 1))
            sign = 1;                                          //标记结果符号
        len1 = num1.size();
        len2 = num2.size();
        if(len1 < len2)                                 //如果被除数小于除法,除数为0
        {
            cout << "商是0;余数是" ;
            print(num2);
            cout << endl;
            return ;
        }
        else                                               //用辗转相除求结果
        {
            for(iter = num1.begin(),i = 0; i < len2 ;++i,++iter)
                temp.push_back(*iter);
            list<char> digit,res;
            for(j = 0; j < 10; j++)
            {
                    digit.clear();
                    digit.push_back(j + '0');
                    res = Mul(num2,digit);
                    res = Sub(temp,res);
                    if(*(res.begin()) == '-')
                        break;
            }
                //cout << endl;print(temp); cout << endl;
            j -= 1;
            if(j > 0)
            {
                digit.clear();
                digit.push_back(j + '0');
                temp = Sub(temp,num2);
                ans.push_back(j + '0');
            }
    
            for(;iter != num1.end();++iter)
            {
                temp.push_back(*iter);
                for(j = 0; j < 10; j++)
                {
                    digit.clear();
                    digit.push_back(j + '0');
                    res = Mul(num2,digit);
                    res = Sub(temp,res);
                    if(*(res.begin()) == '-')
                        break;
                }
                //cout << endl;print(temp); cout << endl;
                j -= 1;
                digit.clear();
                digit.push_back(j + '0');
                res = Mul(num2,digit);
                temp = Sub(temp,res);
                ans.push_back(j + '0');
            }
            if(sign)
                ans.push_front('-');
        }
        cout << "商是";
        print(ans);
        cout << ";余数是" ;
        print(temp);
        cout << endl;
        return ;
    }
    void  Root(list<char> num1)                     //求大数的平方根,用枚举算法暴力搜索算法求
    {
        list<char> ans;
        int len1;
        list<char> digit,temp;
        len1 = num1.size();
        int a = len1 / 2;                            //a是结果的最少位数
        int i;
        digit.push_back('1');
        ans.push_back('1');                        //从ans=10 ^ a 开始搜索
        for(i = 0; i < a - 1; i++)
            ans.push_back('0');
        while(true)                                  //搜到则结束
        {
            temp = Mul(ans,ans);
            temp = Sub(num1,temp);
            if(*(temp.begin()) == '-')                      //如果当前ans的平方大于num1,则得结果
                break;
            ans = Add(ans,digit);
        }
        ans = Sub(ans,digit);
        print(ans);
        cout << endl;
    }
    list<char> translate(string input)
    {
        list<char> res;
        int len = input.length();
        for(int i = 0; i < len; i++)
            res.push_back(input[i]);
        return res;
    }
    void print(list<char> ans)
    {
        list<char>::iterator iter;
        int flag = 1;
        iter = ans.begin();
        if(*iter == '-')
         {
            cout << *iter;
            iter++;
         }
        for(;iter != ans.end(); ++iter)
        {
            if(*iter == '0' && flag)
                continue;
                //cout << (*iter);
            else
            {
                flag = 0;
                cout << (*iter);
            }
        }
        if( flag == 1)
            cout << 0 ;;
        //cout << endl;
    }
    int main()
    {
        char choice;         //选择要进行的运算
        list<char> num1;
        list<char> num2;
        list<char> res;
        string input;
        while(true)
        {
            cout << endl;
            printhelp();
            cin >> choice;
            switch(choice)
            {
                case '1':                      //如果选择加法运算
                    cout << "请输入第一个数" << endl;
                    cin >> input;
                    num1 = translate(input);
                    cout << "请输入第二个数" << endl;
                    cin >> input;
                    num2 = translate(input);
                    res = Add(num1,num2);
                    print(num1);
                    cout << " + " ;
                    print(num2);
                    cout << " = ";
                    print(res);
                    cout << endl;
                    break;
                case '2':                    //选择减法运算
                    cout << "请输入第一个数" << endl;
                    cin >> input;
                    num1 = translate(input);
                    cout << "请输入第二个数" << endl;
                    cin >> input;
                    num2 = translate(input);
                    res = Sub(num1,num2);
                    print(num1);
                    cout <<" - " ;
                    print(num2);
                    cout << " = ";
                    print(res);
                    cout << endl;
                    break;
                case '3':                  //选择乘法运算
                    cout << "请输入第一个数" << endl;
                    cin >> input;
                    num1 = translate(input);
                    cout << "请输入第二个数" << endl;
                    cin >> input;
                    num2 = translate(input);
                    res = Mul(num1,num2);
                    print(num1);
                    cout <<" * " ;
                    print(num2);
                    cout << " = ";
                    print(res);
                    cout << endl;
                    break;
                case '4':                      //选择除法运算
                    cout << "请输入第一个数" << endl;
                    cin >> input;
                    num1 = translate(input);
                    cout << "请输入第二个数" << endl;
                    cin >> input;
                    num2 = translate(input);
                    print(num1);
                    cout << " / " ;
                    print(num2);
                    cout << " = ";
                    if(num2.size() == 1 && (*(num2.begin()) == '0'))
                    {
                        cout << "divided zero error" << endl;
                        break;
                    }
                    Div(num1,num2);
                    //print(res);
                    cout << endl;
                    break;
                case '5':                         //选择求根运算
                    cout << "请输入第一个数" << endl;
                    cin >> input;
                    num1 = translate(input);
                    if(*(num1.begin()) == '-')
                    {
                        cout << "负数没有实数平方根" << endl;
                        break;
                    }
                    Root(num1);
                    break;
                case '6':
                    return 0;
                default:
                      break;
            }
        }
    }
    

    www.cnblogs.com/tenlee
  • 相关阅读:
    寻找大富翁
    C++ STL sort()函数用法
    众数
    平方因子
    Hdu 1089 A+B for Input-Output Practice (I)
    Hdu 1090 A+B for Input-Output Practice (II)
    Hdu 1083 Courses
    Hdu 1069 Monkey and Banana
    Hdu 1062 Text Reverse
    Hdu 1068 Girls and Boys
  • 原文地址:https://www.cnblogs.com/tenlee/p/4420167.html
Copyright © 2011-2022 走看看