`

大数加减乘除求根源码

阅读更多
//设计一个支持大数运算的计算器,其中乘法使用分治法求解。该计算器支持加减乘除还有开方根运算。
#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;
        }
    }
}

































分享到:
评论

相关推荐

    百位大数的加减乘除实现

    以上就是用C语言实现百位大数的加减乘除的基本思路。在实际编程中,还需要处理边界条件、溢出问题以及内存管理等细节。同时,为了提高效率,可以考虑使用更高级的算法,如Karatsuba和Toom-Cook,这些算法在处理大量...

    C语言实现大数计算器(加减乘除)内含源码以及说明书可以自己运行复现.zip

    这将使得加减乘除的逻辑稍微复杂一些,因为需要额外处理符号的变化。 为了运行这个大数计算器,你需要将源代码编译成可执行文件。在C语言中,这通常涉及创建一个main.c文件,导入大数操作的函数库,并调用这些函数...

    大数运算类(支持大数的加减乘除和赋值运算)

    内容索引:VC/C++源码,算法相关,运算类 大数运算类(支持大数的加减乘除和赋值运算),自带了一个示例程序:计算1000的阶乘。  1. 实现原理:任何一个数都可以表示成指数形式,如: N=nEe (0= 2. 如何使用这个类:你...

    大数运算类(支持大数的加减乘除和赋值运算).rar_源码/资料_Visual_C++_

    本资源包“大数运算类(支持大数的加减乘除和赋值运算).rar”显然旨在提供一个实现了大数运算功能的C++类库。 这个类库可能包含了若干个头文件(.h)和源文件(.cpp),用于定义和实现大数类。大数类通常基于数组或...

    大数阶乘的快速实现(C#源码)

    在这个例子中,我们很可能是使用了`BigInteger`,它提供了一套完整的操作大数的方法,包括加减乘除、比较和取模等。 大数阶乘的计算涉及到两个主要问题:大数的存储和高效乘法算法。对于存储,`BigInteger`已经帮...

    易语言脚本实现大数运算源码

    通常,一个易语言的大数运算库可能会包含多个函数或过程,用于执行不同的大数运算操作,如大数的初始化、比较、转换、加减乘除等。在分析这个“content.txt”文件时,我们需要关注以下几个方面: 1. 数据结构:大数...

    易语言源码易语言JS100000大数乘方计算源码.rar

    这通常涉及到链表或者数组的使用,以及自定义的加减乘除操作。同时,为了保证计算效率和正确性,源码中可能包含了错误检查和优化措施。 这个源码对于学习易语言的用户来说是一份宝贵的资源,它可以帮助读者了解如何...

    计算器可计算大数阶乘(源码,BCB开发)

    首先,**计算器设计**通常包括基本的算术运算,如加减乘除,以及更高级的功能,如开方、指数、对数等。在这个特定的项目中,计算器着重实现了**大数阶乘**功能。阶乘运算在常规的计算中容易溢出,因为对于较大的数字...

    java:大数运算的BigInteger类型(整数类)的一些运算

    大数运算的BigInteger类型(整数类)的一些运算关键词相关说明源码运行结果 关键词 import java.math.BigInteger; BigInteger big_number_0=new BigInteger(“A”); A为大数的值,可以是Integer类范围内或外的数。 ...

    易语言源码易语言RSA加解密源码.rar

    1. **大数运算**:RSA涉及到大整数的加减乘除以及模运算,易语言需要提供相应的库函数支持这些操作。 2. **素数检测**:RSA算法的初始化阶段需要生成两个大素数p和q,源码可能包含一种或多种素数生成算法,如米勒-...

    大数运算器(c写的)

    3. **加减乘除运算**:这些基本的算术运算在大数上需要逐位进行,并考虑到进位或借位的情况。例如,大数相加时,从低位到高位逐位相加,若某位的和大于9,则需要向高位进位。乘法则更复杂,需要通过类似于长乘法的...

    RSA加密算法源码

    1. 大数操作:RSA涉及到大整数的加减乘除以及模幂运算,这部分通常需要自定义大数库或者利用现有的大数库实现。 2. 密钥生成:随机选择素数p和q,计算n和φ(n),并找到合适的e和d。 3. 加密函数:接收明文和公钥,...

    VC 大数计算方法附演示代码.rar

    VC 大数计算方法附演示代码,演示大数的加减乘除和赋值运算,示例程序:计算1000的阶乘。简要说一下原理:  1. 实现原理:任何一个数都可以表示成指数形式,如下所示:N=nEe (0= 2. 如何使用这个类:可以把...

    易语言源码易语言四则运算分析计算源码.rar

    - 运算符优先级:四则运算的优先级规则(如先乘除后加减)需要在解析表达式时考虑,这通常涉及栈数据结构的应用。 - 运算过程:通过循环和条件判断实现运算过程,根据运算符的优先级依次处理。 - 错误处理:对于无效...

    带大数运算库的rsa算法

    - **大数运算**:了解大整数的存储方式,例如如何用数组表示大数,以及大数的加减乘除和模逆运算的实现。 - **RSA原理**:熟悉RSA公钥和私钥的生成(大素数的选择、欧拉函数、费马小定理等),以及公钥加密和私钥...

    计算器程序源码(包含全部源码,glade文件,Makefile文件,可执行文件)

    可完整实现带符号的四位是的加减乘除运算,添加大数运算模块可实现任意位数的加减乘除运算,是你学习C语言及GTK界面编程不可不看的案例。 这是本人学习GTK编程的练习之作,有何问题请给我留言。

    rsa.tar.gz_RSA library_RSA大数_rsa

    大数运算在RSA中至关重要,因为RSA涉及到的密钥长度通常非常大,可能达到几百甚至上千位,远超普通整数的范围,因此需要专门的算法来处理这些大数的加减乘除以及模运算。 RSA算法的步骤主要包括以下几点: 1. **...

    信息安全原理大数四则运算及DH算法C语言实现

    在处理诸如公钥密码学、数字签名等安全问题时,常常需要进行大数的加减乘除。大数运算在C语言中通常需要自定义实现,因为标准库提供的整型类型如int或long int无法处理大数。实现大数运算通常涉及位操作、数组存储和...

    易语言多位数运算

    10. **剪切、复制、粘贴功能**:在实现易语言的大数运算源码中,可能会包含用于用户界面交互的剪切、复制和粘贴功能,使得用户可以方便地操作和传输大数。 了解并掌握这些概念和算法是进行易语言多位数运算的关键。...

    大数计算源代码

    用来计算特别大的数的加减乘除乘方什么的,理论上来说,没有位数限制,如果你的内存足够大,CPU足够强劲。 可速度却不怎么样,如有兄弟改进了,麻烦发到这上面来大家共享~~~ 采用链表实现,每个节点里放下4位,即...

Global site tag (gtag.js) - Google Analytics