(C++源代码)支持带小数点的大数四则运算

常见的大数四则运算都不支持带小数点,这个是我最近编写的支持带小数点的大数四则运算C++源代码。欢迎识货者欣赏、收藏、点赞、评论、使用。

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
inline int compare(string str1,string str2) {//相等返回0,大于返回1,小于返回-1
         if (str1.size()>str2.size()) return 1; //长度长的整数大于长度小的整数
    else if (str1.size()<str2.size()) return -1;
    else                              return str1.compare(str2); //若长度相等,则头到尾按位比较
}
string SUB_INT(string str1,string str2);
string ADD_INT(string str1,string str2) {//高精度加法
    int sign=1; //sign 为符号位
    string str;
    if (str1[0]=='-') {
        if (str2[0]=='-') {
            sign=-1;
            str=ADD_INT(str1.erase(0,1),str2.erase(0,1));
        } else {
            str=SUB_INT(str2,str1.erase(0,1));
        }
    } else {
        if (str2[0]=='-') {
            str=SUB_INT(str1,str2.erase(0,1));
        } else { //把两个整数对齐,短整数前面加0补齐
            string::size_type L1,L2;
            int i;
            L1=str1.size();
            L2=str2.size();
            if (L1<L2) {
                for (i=1;i<=(int)(L2-L1);i++) str1="0"+str1;
            } else {
                for (i=1;i<=(int)(L1-L2);i++) str2="0"+str2;
            }
            int int1=0,int2=0; //int2 记录进位
            for (i=str1.size()-1;i>=0;i--) {
                int1=(int(str1[i])-'0'+int(str2[i])-'0'+int2)%10;
                int2=(int(str1[i])-'0'+int(str2[i])-'0'+int2)/10;
                str=char(int1+'0')+str;
            }
            if (int2!=0) str=char(int2+'0')+str;
        }
    }
    //运算后处理符号位
    if ((sign==-1)&&(str[0]!='0')) str="-"+str;
    return str;
}
string SUB_INT(string str1,string str2) {//高精度减法
    int sign=1; //sign 为符号位
    string str;
    int i,j;
    if (str2[0]=='-') {
        str=ADD_INT(str1,str2.erase(0,1));
    } else {
        int res=compare(str1,str2);
        if (res==0) return "0";
        if (res<0) {
            sign=-1;
            string temp =str1;
            str1=str2;
            str2=temp;
        }
        string::size_type tempint;
        tempint=str1.size()-str2.size();
        for (i=str2.size()-1;i>=0;i--) {
            if (str1[i+tempint]<str2[i]) {
                j=1;
                while (1) {
                    if (str1[i+tempint-j]=='0') {
                        str1[i+tempint-j]='9';
                        j++;
                    } else {
                        str1[i+tempint-j]=char(int(str1[i+tempint-j])-1);
                        break;
                    }
                }
                str=char(str1[i+tempint]-str2[i]+':')+str;
            } else {
                str=char(str1[i+tempint]-str2[i]+'0')+str;
            }
        }
        for (i=tempint-1;i>=0;i--) str=str1[i]+str;
    }
    str.erase(0,str.find_first_not_of('0')); if (str.empty()) str="0";//去除结果中的前导0
    if ((sign==-1) && (str[0]!='0')) str ="-"+str;
    return str;
}
string MUL_INT(string str1,string str2) {//高精度乘法
    int sign=1; //sign 为符号位
    string str;
    if (str1[0]=='-') {
        sign*=-1;
        str1 =str1.erase(0,1);
    }
    if (str2[0]=='-') {
        sign*=-1;
        str2 =str2.erase(0,1);
    }
    int i,j;
    string::size_type L1,L2;
    L1=str1.size();
    L2=str2.size();
    for (i=L2-1;i>=0;i--) { //模拟手工乘法竖式
        string tempstr;
        int int1=0,int2=0,int3=int(str2[i])-'0';
        if (int3!=0) {
            for (j=1;j<=(int)(L2-1-i);j++) tempstr="0"+tempstr;
            for (j=L1-1;j>=0;j--) {
                int1=(int3*(int(str1[j])-'0')+int2)%10;
                int2=(int3*(int(str1[j])-'0')+int2)/10;
                tempstr=char(int1+'0')+tempstr;
            }
            if (int2!=0) tempstr=char(int2+'0')+tempstr;
        }
        str=ADD_INT(str,tempstr);
    }
    str.erase(0,str.find_first_not_of('0')); if (str.empty()) str="0";//去除结果中的前导0
    if ((sign==-1) && (str[0]!='0')) str="-"+str;
    return str;
}
string DIVIDE_INT(string str1,string str2,int flag) {//高精度除法。flag==1时,返回商; flag==0时,返回余数
    string quotient,residue; //定义商和余数
    int sign1=1,sign2=1;
    if (str2 == "0") {  //判断除数是否为0
        quotient= "ERROR!";
        residue = "ERROR!";
        if (flag==1) return quotient;
        else         return residue ;
    }
    if (str1=="0") { //判断被除数是否为0
        quotient="0";
        residue ="0";
    }
    if (str1[0]=='-') {
        str1   = str1.erase(0,1);
        sign1 *= -1;
        sign2  = -1;
    }
    if (str2[0]=='-') {
        str2   = str2.erase(0,1);
        sign1 *= -1;
    }
    int res=compare(str1,str2);
    if (res<0) {
        quotient="0";
        residue =str1;
    } else if (res == 0) {
        quotient="1";
        residue ="0";
    } else {
        string::size_type L1,L2;
        L1=str1.size();
        L2=str2.size();
        string tempstr;
        tempstr.append(str1,0,L2-1);
        for (int i=L2-1;i<(int)L1;i++) { //模拟手工除法竖式
            tempstr=tempstr+str1[i];
            tempstr.erase(0,tempstr.find_first_not_of('0')); if (tempstr.empty()) tempstr="0";
            for (char ch='9';ch>='0';ch--) { //试商
                string str;
                str=str+ch;
                if (compare(MUL_INT(str2,str),tempstr)<=0) {
                    quotient=quotient+ch;
                    tempstr =SUB_INT(tempstr,MUL_INT(str2,str));
                    break;
                }
            }
        }
        residue=tempstr;
    }
    quotient.erase(0,quotient.find_first_not_of('0')); if (quotient.empty()) quotient="0";//去除结果中的前导0
    if ((sign1==-1)&&(quotient[0]!='0')) quotient="-"+quotient;
    if ((sign2==-1)&&(residue [0]!='0')) residue ="-"+residue ;
    if (flag==1) return quotient;
    else         return residue ;
}
string DIV_INT(string str1,string str2) {//高精度除法,返回商
    return DIVIDE_INT(str1,str2,1);
}
string MOD_INT(string str1,string str2) {//高精度除法,返回余数
    return DIVIDE_INT(str1,str2,0);
}
int main(int argc,char **argv) {
    char ch;
    string chs,s1,s2,s3,res,res1,prs;
    int e1,e2,e,ed;//小数位数
    int f1,f2;//正负符号
    int d1,d2;//小数点位置
    int i,L;
    int pr;//小数除法除不尽时默认保留小数点后位数。默认100,可用一个命令行参数设置为1~10000之间的数

    pr=100;
    if (argc>=2) pr=atoi(argv[1]);
    if (pr<1 || 10000<pr) pr=100;
    prs=""; for (i=0;i<pr;i++) prs=prs+"0";

    while (1) {
        cout<<"Input big_decimal1 OP big_decimal2 (OP is one of +-*/%, ^Z to Exit):"<<endl;
        if (!(cin>>s1>>chs>>s2)) break;//
        ch=chs[0];
        if (s1.find('.')==string::npos
         && s2.find('.')==string::npos) {
            switch (ch) {
                case '+':res=ADD_INT(s1,s2);break;
                case '-':res=SUB_INT(s1,s2);break;
                case '*':res=MUL_INT(s1,s2);break;
                case '/':res=DIV_INT(s1,s2);break;
                case '%':res=MOD_INT(s1,s2);break;
                default :
                    res="Operator "+chs+" is not supported!";
                break;
            }
        } else {
            if (s1.find('.')==string::npos) s1=s1+".0";//没有小数点,末尾添加.0
            f1=1;if (s1[0]=='-') {f1=-1; s1=s1.substr(1);}//提取正负号
            d1=s1.find('.');//小数点位置
            e1=s1.size()-d1-1;//小数位数
            s1=s1.substr(0,d1)+s1.substr(d1+1,e1);//去掉小数点

            if (s2.find('.')==string::npos) s2=s2+".0";//没有小数点,末尾添加.0
            f2=1;if (s2[0]=='-') {f2=-1; s2=s2.substr(1);}//提取正负号
            d2=s2.find('.');//小数点位置
            e2=s2.size()-d2-1;//小数位数
            s2=s2.substr(0,d2)+s2.substr(d2+1,e2);//去掉小数点

            switch (ch) {
                case '+':
                    if (e1>e2) {e=e1;for (i=0;i<e1-e2;i++) s2=s2+"0";}//被加数s1小数位数多,  加数s2末尾添加0,和被加数s1小数位一样多
                    if (e2>e1) {e=e2;for (i=0;i<e2-e1;i++) s1=s1+"0";}//  加数s2小数位数多,被加数s1末尾添加0,和  加数s2小数位一样多
                    if (f1==f2) {//若都正或都负
                        res1=ADD_INT(s1,s2);//调用整数加法运算
                        res=res1.substr(0,res1.size()-e)+"."+res1.substr(res1.size()-e);//e位小数
                        if (f1==-1 && f2==-1) res="-"+res;//若s1和s2都是负数,前面加负号
                    } else {//若一正一负
                        if (f1== 1 && f2==-1) {
                            res1=SUB_INT(s1,s2);//调用整数减法运算
                        } else if (f1==-1 && f2== 1) {
                            res1=SUB_INT(s2,s1);//调用整数减法运算
                        }
                        res=res1.substr(0,res1.size()-e)+"."+res1.substr(res1.size()-e);//e位小数
                    }
                break;
                case '-':
                    if (e1>e2) {e=e1;for (i=0;i<e1-e2;i++) s2=s2+"0";}//被减数s1小数位数多,  减数s2末尾添减0,和被减数s1小数位一样多
                    if (e2>e1) {e=e2;for (i=0;i<e2-e1;i++) s1=s1+"0";}//  减数s2小数位数多,被减数s1末尾添减0,和  减数s2小数位一样多
                           if (f1== 1 && f2== 1) {//s1正,s2正
                        res1=SUB_INT(s1,s2);//调用整数减法运算
                        res=res1.substr(0,res1.size()-e)+"."+res1.substr(res1.size()-e);//e位小数
                    } else if (f1== 1 && f2==-1) {//s1正,s2负
                        res1=ADD_INT(s1,s2);//调用整数加法运算
                        res=res1.substr(0,res1.size()-e)+"."+res1.substr(res1.size()-e);//e位小数
                    } else if (f1==-1 && f2== 1) {//s1负,s2正
                        res1=ADD_INT(s1,s2);//调用整数加法运算
                        res=res1.substr(0,res1.size()-e)+"."+res1.substr(res1.size()-e);//e位小数
                        res="-"+res;//前面加负号
                    } else if (f1==-1 && f2==-1) {//s1负,s2负
                        res1=SUB_INT(s2,s1);//调用整数减法运算
                        res=res1.substr(0,res1.size()-e)+"."+res1.substr(res1.size()-e);//e位小数
                    }
                break;
                case '*':
                    s1.erase(0,s1.find_first_not_of('0')); if (s1.empty()) s1="0";//去除前导0
                    s2.erase(0,s2.find_first_not_of('0')); if (s2.empty()) s2="0";//去除前导0
                    res1=MUL_INT(s1,s2);//调用整数乘法运算
                    e=e1+e2;//乘法结果的小数位数e等于被乘数和乘数小数位数之和
                    L=res1.size();
                    if (e>=L) for (i=0;i<e-L+1;i++) res1="0"+res1;//结果小数位数≥整数结果长度,左边补0
                    res=res1.substr(0,res1.size()-e)+"."+res1.substr(res1.size()-e);//e位小数
                    if (f1!=f2) res="-"+res;//被乘数和乘数正负号不同,前面加负号
                break;
                case '/':
                    //将被除数s1小数点右移ed位直到被除数s1≥除数s2
                    ed=0;
                    while (1) {
                        L=compare(s1.substr(0,s1.size()-e1),s2.substr(0,s2.size()-e2));
                        if (L==-1) {
                            if (e1>0) e1--;
                            else s1=s1+"0";
                            ed++;
                        } else break;//
                    }

                    //将s1乘10的pr次方,目的是在除不尽时让结果保留pr位小数
                    s1=s1+prs;

                    s1.erase(0,s1.find_first_not_of('0')); if (s1.empty()) s1="0";//去除前导0
                    s2.erase(0,s2.find_first_not_of('0')); if (s2.empty()) s2="0";//去除前导0
                    res1=DIV_INT(s1,s2);//调用整数除法运算
                    e=pr+ed+e1-e2;//结果的小数位数e为pr+ed+e1-e2
                    L=res1.size();
                    if (e>=L) for (i=0;i<e-L+1;i++) res1="0"+res1;//结果小数位数≥整数结果长度,左边补0
                    res=res1.substr(0,res1.size()-e)+"."+res1.substr(res1.size()-e);//e位小数
                    if (f1!=f2) res="-"+res;//被除数和除数正负号不同,前面加负号
                break;
                case '%':
                    res="Operator "+chs+" is not supported for decimal!";
                break;
                default:
                    res="Operator "+chs+" is not supported!";
                break;
            }
        }
        if (res.find('.')!=string::npos) {//结果中有小数点
            res=res.substr(0,res.find_last_not_of('0')+1);//去除小数末尾的0
            if (res[res.size()-1]=='.') res=res.substr(0,res.size()-1);//如果末尾是.,连.也去掉
        }
        cout<<"="<<res<<endl;
    }
    return(0);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵4老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值