C++で非常に長い数値を扱う方法(longlong型の整数は格納できない)

C++で非常に長い数値を扱う方法(longlong型の整数は格納できない)

C++ では、数値が long long 型の範囲を超える場合、文字列またはサードパーティ ライブラリ (Boost.Multiprecision など) を使用して、非常に長い数値を表現および処理することを検討できます。サードパーティ製ライブラリを使用するには、必要なサードパーティ製ライブラリをダウンロードしてインストールする必要がありますが、ここでは紹介しません。

ここでは、文字列を使用して非常に長い数値を表現し、処理する方法を紹介します。この記事では、C++ 文字列を使用して、非常に長い数値の加算、減算、乗算、除算の演算を実装する方法を紹介します。

1.非負の非常に大きな数値が奇数か偶数かを判断します。ソース コードは次のとおりです。

#include <iostream>  
#include <string>
using namespace std;  

int main() {  
//string s = "123456789123456789123456789";
cout << "请输入一个正整数:" << endl;
    cin >> s;
    // s.size()是字符串的长度,即由多少字符组成的, 字符串的最后一位字符即s[s.size() - 1]
    char c = s[s.size() - 1];
    cout << "最后一位数字是" << c << endl;  
    // 将一个整数数字字符变成整数,我们只需要将它减字符'0'
    int i = c - '0';
    if (i % 2 == 0) {
        cout << s << "是偶数";
    } else {
        cout << s << "是奇数";
    }
        
    return 0;  
}

2. 2 つの非常に大きな正の整数のサイズを決定します。

#include <iostream>  
#include <string>  
  
using namespace std;  
  
bool Lower(string str1, string str2){     
    //长度长的一定大(这里假设除了0以外,都没有前导0),长度相等则字典序小的数字更小
    return str1.size()<str2.size()||(str1.size()==str2.size()&&str1<str2);
} 
  
int main() {  
    cout << "请输入两个超大正整数:" << endl;
	string a, b; 
	cin >> a >> b; 
    if (Lower(a, b)){
    	cout << a << "小于" << b << endl;
	}
	else{
		cout << a << "大于" << b << endl;
	}
	  
    return 0;  
}

加算、減算、乗算、除算の演算の実装方法を以下に紹介します。特に、加算演算と減算演算は、負でない整数演算に限定されます。負の数の加算演算と減算演算は、何らかの形式の加算演算や減算演算と同等である可能性があるため、考慮されません。乗算演算と除算演算は、大きい値のみを考慮します。計算: 除算では大きな整数演算のみが考慮され、計算結果は小数点以下 6 桁まで正確です (小数点以下 6 桁以降は直接破棄されます)。

参考https://blog.songjiahao.com/archives/382

3. 非負の大きな整数の加算

大きな数の加算の実装は、垂直式の計算方法を模倣しており、1の位から1つずつ加算し、そのつど桁上がりを考慮するだけです。読み取った文字列の0番目が最上位ビットなので、逆順に文字列にアクセスして各ビットを計算します。同様に、計算中に取得される各ビットは逆順であるため、最終結果も逆にする必要があります。

加算すると最終桁が 1 つ増える (最上位ビットから繰り上がる) 場合があるので、忘れずに処理してください。

最後に、いくつかの特殊なケースを考えてみましょう。たとえば、両方の数値が 0 であるか、どちらか一方が 0 の場合、結果を迅速に取得し、走査プロセスを節約できます。

コードを実装する

#include <iostream>  
#include <string>  
#include <algorithm>

using namespace std; 

//判断是否为0,全部为0的数字就是0,比如00000
bool CheckZero(const string &str){      //检查是否等于0
    int size=str.size();                //如果全是0则为0,这里假设不会有带符号的+00000或者-00000作为输入
    for(int i=0;i<size;i++)
        if(str[i]!='0') return false;
    return true;
}

string Add(string str1, string str2){
    //关于0的处理
    if(CheckZero(str1)&&CheckZero(str2)) return "0";    //如果都是0
    else if(CheckZero(str1)) return str2;               //如果有个一为0
    else if(CheckZero(str2)) return str1;
    string ans;
    int i=str1.size()-1,j=str2.size()-1;
    int flag=0;                                         //进位标记
    while(i>=0||j>=0||flag){
        int numa=i>=0?str1[i--]-'0':0;                  //如果所有位都访问完毕,对应的位置用0代替
        int numb=j>=0?str2[j--]-'0':0;
        flag=numa+numb+flag;                            //计算两位的和
        ans+='0'+flag%10;                               //取个位保存在答案中
        flag/=10;                                       //计算进位
    }
    reverse(ans.begin(),ans.end());
    return ans;
}

int main(){
	cout << "请输入两个正整数:" << endl;
	string a, b;
	cin >> a >> b;
	string result = Add(a, b);  
    cout << "和:" << result << endl;  
    return 0;  
}

4. 負でない大きな整数の減算

大きな数の減算の実装も、垂直式の計算方法を模倣しています。一の位から数えて毎回一桁ずつ計算し、次の桁が借用されているかどうかで借用した桁を減算し、次に現在の桁が十分に減算されているかどうかを判断します。前の桁が借用され、操作が完了するまで減算されます。同様に、一の位から計算しなければならないので、計算結果も逆の順序になる必要があり、最後に結果を逆にすることを忘れないでください。

減算中、先頭の 0 が表示されることがあります。先頭の 0 を忘れずにクリアしてください。

最後に、2 つの数値が同じである、または 1 つの数値が 0 であるなど、いくつかの特殊なケースを考えてみましょう。結果を直接取得できるため、複雑な処理を回避できます。

コードを実装する

#include <iostream>  
#include <string>  
#include <algorithm>

using namespace std; 

//判断两个超大正整数的大小 
bool Lower(string str1, string str2){     
    //长度长的一定大(这里假设除了0以外,都没有前导0),长度相等则字典序小的数字更小
    return str1.size()<str2.size()||(str1.size()==str2.size()&&str1<str2);
} 

//判断是否为0,全部为0的数字就是0,比如00000
bool CheckZero(const string &str){      //检查是否等于0
    int size=str.size();                //如果全是0则为0,这里假设不会有带符号的+00000或者-00000作为输入
    for(int i=0;i<size;i++)
        if(str[i]!='0') return false;
    return true;
}

string Sub(string str1, string str2){
    //处理0的情况
    if(str1==str2||(CheckZero(str1)&&CheckZero(str2))) return "0";  //如果两数相等或者都是0
    else if(CheckZero(str1)) return "-"+str2;                       //如果第一个数字为0
    else if(CheckZero(str2)) return str1;                           //如果第二个数字为0
    //定正负
    int negative=0;                     //结果的正负号
    if(Lower(str1,str2)){
        swap(str1,str2);                //保证str1大于str2
        negative=1;                     //如果str1小于str2,则结果过为负值
    }
    string ans;
    int i=str1.size()-1,j=str2.size()-1;//逆序开始处理
    int flag=0;                         //借位标记
    while(i>=0||j>=0){
        int numa=i>=0?str1[i--]-'0':0;  //取每一位,因为长度可能不同所以当某一个已经读取完毕时对应位置取0
        int numb=j>=0?str2[j--]-'0':0;
        numa-=flag;                     //先减去借位
        if(numa<numb){                  //如果不够减则向上一位借位(只可能借一位)
            numa+=10;                   //借位并记录借位
            flag=1;
        }
        else flag=0;                    //如果不借位,则借位标记为0
        ans+='0'+numa-numb;             //计算当前位置并保存
    }
    i=ans.size()-1;
    while(ans[i]=='0') i--;
    ans=ans.substr(0,i+1);              //去除前导0,如111-110=1
    if(negative) ans+='-';              //如果计算结果是负数,添加负数符号
    reverse(ans.begin(),ans.end());     //因为是逆序计算得到的结果,所以需要翻转一下
    return ans;
}

int main(){
	cout << "请输入两个正整数:" << endl;
	string a, b;
	cin >> a >> b;
	string result = Sub(a, b);  
    cout << "差: " << result << endl;     
    return 0;  
}

5. 大きな整数の乗算

大きな数値の乗算の実装にも、垂直方向の計算方法が使用されます。一の位から始めて、被乗数と乗数の積を 1 桁ずつ計算し、作成した大きな数の加算を使用して最終結果を累積します。ただし、大きな数の乗算では正負の問題を考慮する必要があるため、正負の符号を処理する必要があり、2 つの数値の符号に対して XOR を使用することで、最終的に積の結果の正負を決定できます。

乗算。乗数の各桁には対応する重み (1 億) があるため、乗数の各桁の積を計算するときは、その位置の重みを考慮し、積の後に対応する値を追加する必要があります。ゼロで十分です。

最後に、いくつかの特殊なケースについて考えます。たとえば、2 つの数値のうちの 1 つが 0 である限り、結果は 0 になります。

コードを実装する

#include <iostream>  
#include <string>  
#include <algorithm>

using namespace std; 

//判断两个超大正整数的大小 
bool Lower(string str1, string str2){     
    //长度长的一定大(这里假设除了0以外,都没有前导0),长度相等则字典序小的数字更小
    return str1.size()<str2.size()||(str1.size()==str2.size()&&str1<str2);
} 

//判断是否为负,只需要判断第一位是不是负号即可,这里不考虑正号的存在,即认为不使用正号
bool CheckNegative(const string &str){  //检查是否为负数
    return str[0]=='-';
}

//判断是否为0,全部为0的数字就是0,比如00000
bool CheckZero(const string &str){      //检查是否等于0
    int size=str.size();                //如果全是0则为0,这里假设不会有带符号的+00000或者-00000作为输入
    for(int i=0;i<size;i++)
        if(str[i]!='0') return false;
    return true;
}

string Add(string str1, string str2){
    //关于0的处理
    if(CheckZero(str1)&&CheckZero(str2)) return "0";    //如果都是0
    else if(CheckZero(str1)) return str2;               //如果有个一为0
    else if(CheckZero(str2)) return str1;
    string ans;
    int i=str1.size()-1,j=str2.size()-1;
    int flag=0;                                         //进位标记
    while(i>=0||j>=0||flag){
        int numa=i>=0?str1[i--]-'0':0;                  //如果所有位都访问完毕,对应的位置用0代替
        int numb=j>=0?str2[j--]-'0':0;
        flag=numa+numb+flag;                            //计算两位的和
        ans+='0'+flag%10;                               //取个位保存在答案中
        flag/=10;                                       //计算进位
    }
    reverse(ans.begin(),ans.end());
    return ans;
}

string Mul(string str1, string str2){
    if(CheckZero(str1)||CheckZero(str2)) return "0";    //如果有一个为0,则结果为0
 
    int negative=0,negastr1=0,negastr2=0;               //定正负
    if(CheckNegative(str1)){                            //确定正负号标记,并且去掉-字符
        negastr1=1; str1=str1.substr(1,str1.size()-1);
    }
    if(CheckNegative(str2)){
        negastr2=1; str2=str2.substr(1,str2.size()-1);
    }
    negative=negastr1^negastr2;                         //异或运算确定结果的正负号
 
    string ans;
    if(Lower(str1,str2)) swap(str1,str2);               //保证str1大于等于str2
    int size1=str1.size(),size2=str2.size();
    for(int i=size2-1;i>=0;i--){                        //遍历较小数字的每一位
        string temp(size2-1-i,'0');                     //temp为str1乘以str2[i]的积,根据str2[i]的权重(个十百千万,补充对应个数的0)
        int flag=0;                                     //进位标记
        for(int j=size1-1;j>=0;j--){                    //temp
            flag+=(str1[j]-'0')*(str2[i]-'0');
            temp.push_back('0'+(flag%10));
            flag/=10;
        }
        if(flag) temp.push_back('0'+flag);              //如果最高位还有进位
        reverse(temp.begin(),temp.end());
        ans=Add(ans,temp);                              //将计算结果累加到最终的结果上
    }
    if(negative) ans="-"+ans;                           //处理结果的正负号
    return ans;
}

int main(){
	cout << "请输入两个整数:" << endl;
	string a, b;
	cin >> a >> b;
	string result = Mul(a, b);  
    cout << "积:" << result << endl;     
    return 0;  
}

6. 大きな整数の除算、計算結果は小数点以下 6 桁まで正確です (小数点以下 6 桁以降は直接破棄されます)。

ビジネスなど 3.700014[5800933124]

大きな数の除算の実装も、除算式メソッドを使用して計算されます。まず、XOR メソッドを使用して結果の符号を決定します。2 つの数値を除算する場合、最初の数値が 2 番目の数値以上の場合、結果は 1 以上になる必要があります。そうでない場合、結果は 1 未満になります。したがって、1 未満の結果表現を実現するには、結果を小数点以下 6 桁まで正確にします。ここで使用される方法は、純粋な 10 進数であるかどうかを事前に判断し、最初の数値の末尾に 6 つのゼロを追加し、除算式を使用して計算することです。最初の数字の先頭から、商の計算に使用できる長さの最初の数字を探し、商を計算し、計算が完了するまで仮の余りに 1 桁を加えて次の商を計算します。

割り算では約数が0になる場合もあるので、事前に判断して計算する必要があります。また、商の計算方法は計算過程で大きな数値の減算演算を使用するため、累積が0になる(長さが増加する)状況が発生する可能性があり、これは大小の比較と決定に影響を与えるため、注意が必要です。取り扱い。

最後に、特殊な場合について考えます。たとえば、被除数が 0 の場合、結果 0.000000 を直接出力できます。

コードを実装する

#include <iostream>  
#include <string>  
#include <algorithm>

using namespace std; 

//判断两个超大正整数的大小 
bool Lower(string str1, string str2){     
    //长度长的一定大(这里假设除了0以外,都没有前导0),长度相等则字典序小的数字更小
    return str1.size()<str2.size()||(str1.size()==str2.size()&&str1<str2);
} 

//判断是否为负,只需要判断第一位是不是负号即可,这里不考虑正号的存在,即认为不使用正号
bool CheckNegative(const string &str){  //检查是否为负数
    return str[0]=='-';
}

//判断是否为0,全部为0的数字就是0,比如00000
bool CheckZero(const string &str){      //检查是否等于0
    int size=str.size();                //如果全是0则为0,这里假设不会有带符号的+00000或者-00000作为输入
    for(int i=0;i<size;i++)
        if(str[i]!='0') return false;
    return true;
}

//大数减法
string Sub(string str1, string str2){
    //处理0的情况
    if(str1==str2||(CheckZero(str1)&&CheckZero(str2))) return "0";  //如果两数相等或者都是0
    else if(CheckZero(str1)) return "-"+str2;                       //如果第一个数字为0
    else if(CheckZero(str2)) return str1;                           //如果第二个数字为0
    //定正负
    int negative=0;                     //结果的正负号
    if(Lower(str1,str2)){
        swap(str1,str2);                //保证str1大于str2
        negative=1;                     //如果str1小于str2,则结果过为负值
    }
    string ans;
    int i=str1.size()-1,j=str2.size()-1;//逆序开始处理
    int flag=0;                         //借位标记
    while(i>=0||j>=0){
        int numa=i>=0?str1[i--]-'0':0;  //取每一位,因为长度可能不同所以当某一个已经读取完毕时对应位置取0
        int numb=j>=0?str2[j--]-'0':0;
        numa-=flag;                     //先减去借位
        if(numa<numb){                  //如果不够减则向上一位借位(只可能借一位)
            numa+=10;                   //借位并记录借位
            flag=1;
        }
        else flag=0;                    //如果不借位,则借位标记为0
        ans+='0'+numa-numb;             //计算当前位置并保存
    }
    i=ans.size()-1;
    while(ans[i]=='0') i--;
    ans=ans.substr(0,i+1);              //去除前导0,如111-110=1
    if(negative) ans+='-';              //如果计算结果是负数,添加负数符号
    reverse(ans.begin(),ans.end());     //因为是逆序计算得到的结果,所以需要翻转一下
    return ans;
}

string Div(string str1, string str2){
    //处理除数为0的情况和被除数为0的情况
    if(CheckZero(str2)) return "The divisor cannot be zero!";
    else if(CheckZero(str1)) return "0.000000";
 
    int negative=0,negastr1=0,negastr2=0;               //定正负
    if(CheckNegative(str1)){                            //确定正负号标记,并且去掉-
        negastr1=1; str1=str1.substr(1,str1.size()-1);
    }
    if(CheckNegative(str2)){
        negastr2=1; str2=str2.substr(1,str2.size()-1);
    }
    negative=negastr1^negastr2;                         //异或运算确定结果的正负号
 
    int point=0;                                        //结果是否为纯小数
    if(Lower(str1,str2)) point=1;                       //如果str1小于str2,则计算为纯小数
    string ans;                                         //计算结果
    str1+=string(6,'0');                                //补足6个0,用于计算小数位
 
    int size1=str1.size(),size2=str2.size();
    int i=size2-1;                                      //商第一位的位置
    string temp=str1.substr(0,i);                       //从str1上取size2-1个字符
    for(i;i<size1;i++){
        temp+=str1[i];                                  //从后边拿出一位,预先处理可以防止结尾处越界
        int cnt=0;                                      //当前位的商,也就是temp中包含了多少个str2,使用减法                                          //如果temp不为0,则计算商
        while(Lower(str2,temp)||temp==str2){            //如果当前位商不为0,则计算商
            temp=Sub(temp,str2);
            cnt++;
        }
        if(temp=="0") temp.clear();                     //如果某次计算结果为0,则清空,避免0的堆积,比如111000 111
        ans.push_back('0'+cnt);                         //保存商
    }
    i=0;
    while(ans[i]=='0') i++;
    ans=ans.substr(i,ans.size()-i);                     //去除前导0
    if(point){                                          //如果是纯小数,补足6位并添加小数点
        int len=6-ans.size();
        ans="0."+string(len,'0')+ans;
    }
    else ans.insert((ans.end()-6),'.');                 //如果不是小数,则只需要插入小数点       
    if(negative) ans="-"+ans;                           //最后一步骤,如果是负数带上负号
    return ans;
}

int main(){
	cout << "请输入两个整数:" << endl;
	string a, b;
	cin >> a >> b;
	string result = Div(a, b);  
    cout << "商(6位小数后直接舍去):" << result << endl;     
    return 0;  
}

7. 最後に大きな数の四則演算に統合します

加算および減算演算は、負でない整数演算に限定されます。負の数の加算および減算演算は、何らかの形式の加算または減算演算と同等であるため、考慮されません。乗算および除算演算は、大きな整数演算のみを考慮します。小数点以下の計算ではなく、除算 大きな整数演算のみが考慮され、計算結果は小数点以下 6 桁まで正確です (小数点以下 6 桁以降は直接破棄されます)。ソースコードは次のとおりです。

#include <iostream>  
#include <string>  
#include <algorithm>
  
using namespace std;  
  
//大数四则运算,两个参数都不能为空
string Add(string str1, string str2);       //大数加法
string Sub(string str1, string str2);       //大数减法
string Mul(string str1, string str2);       //大数乘法
string Div(string str1, string str2);       //大数除法
bool Lower(string str1, string str2);       //大数比较(小于)
bool CheckZero(const string &str);          //检查是不是0,比如0000认为是0
bool CheckNegative(const string &str);      //检查是不是负数
void ShowMenu();                            //提示菜单
void ShowMenu(char choice);                 //二级菜单
int main(){
    string a,b;
    char ch;
    ShowMenu();
    while(cin>>ch&&ch!='q'){                //循环打印菜单并提示用户输入
        ShowMenu(ch);
        cin>>a>>b;
        switch(ch){
            case 'a':cout<<a<<" + "<<b<<" = "<<Add(a,b)<<endl;break;
            case 'b':cout<<a<<" - "<<b<<" = "<<Sub(a,b)<<endl;break;
            case 'c':cout<<a<<" * "<<b<<" = "<<Mul(a,b)<<endl;break;
            case 'd':cout<<a<<" / "<<b<<" = "<<Div(a,b)<<endl;break;
        }
        ShowMenu();
    }
    return 0;
}
string Add(string str1, string str2){
    //关于0的处理
    if(CheckZero(str1)&&CheckZero(str2)) return "0";    //如果都是0
    else if(CheckZero(str1)) return str2;               //如果有个一为0
    else if(CheckZero(str2)) return str1;
    string ans;
    int i=str1.size()-1,j=str2.size()-1;
    int flag=0;                                         //进位标记
    while(i>=0||j>=0||flag){
        int numa=i>=0?str1[i--]-'0':0;                  //如果所有位都访问完毕,对应的位置用0代替
        int numb=j>=0?str2[j--]-'0':0;
        flag=numa+numb+flag;                            //计算两位的和
        ans+='0'+flag%10;                               //取个位保存在答案中
        flag/=10;                                       //计算进位
    }
    reverse(ans.begin(),ans.end());
    return ans;
}
string Sub(string str1, string str2){
    //处理0的情况
    if(str1==str2||(CheckZero(str1)&&CheckZero(str2))) return "0";  //如果两数相等或者都是0
    else if(CheckZero(str1)) return "-"+str2;                       //如果第一个数字为0
    else if(CheckZero(str2)) return str1;                           //如果第二个数字为0
    //定正负
    int negative=0;                     //结果的正负号
    if(Lower(str1,str2)){
        swap(str1,str2);                //保证str1大于str2
        negative=1;                     //如果str1小于str2,则结果过为负值
    }
    string ans;
    int i=str1.size()-1,j=str2.size()-1;//逆序开始处理
    int flag=0;                         //借位标记
    while(i>=0||j>=0){
        int numa=i>=0?str1[i--]-'0':0;  //取每一位,因为长度可能不同所以当某一个已经读取完毕时对应位置取0
        int numb=j>=0?str2[j--]-'0':0;
        numa-=flag;                     //先减去借位
        if(numa<numb){                  //如果不够减则向上一位借位(只可能借一位)
            numa+=10;                   //借位并记录借位
            flag=1;
        }
        else flag=0;                    //如果不借位,则借位标记为0
        ans+='0'+numa-numb;             //计算当前位置并保存
    }
    i=ans.size()-1;
    while(ans[i]=='0') i--;
    ans=ans.substr(0,i+1);              //去除前导0,如111-110=1
    if(negative) ans+='-';              //如果计算结果是负数,添加负数符号
    reverse(ans.begin(),ans.end());     //因为是逆序计算得到的结果,所以需要翻转一下
    return ans;
}
string Mul(string str1, string str2){
    if(CheckZero(str1)||CheckZero(str2)) return "0";    //如果有一个为0,则结果为0
 
    int negative=0,negastr1=0,negastr2=0;               //定正负
    if(CheckNegative(str1)){                            //确定正负号标记,并且去掉-字符
        negastr1=1; str1=str1.substr(1,str1.size()-1);
    }
    if(CheckNegative(str2)){
        negastr2=1; str2=str2.substr(1,str2.size()-1);
    }
    negative=negastr1^negastr2;                         //异或运算确定结果的正负号
 
    string ans;
    if(Lower(str1,str2)) swap(str1,str2);               //保证str1大于等于str2
    int size1=str1.size(),size2=str2.size();
    for(int i=size2-1;i>=0;i--){                        //遍历较小数字的每一位
        string temp(size2-1-i,'0');                     //temp为str1乘以str2[i]的积,根据str2[i]的权重(个十百千万,补充对应个数的0)
        int flag=0;                                     //进位标记
        for(int j=size1-1;j>=0;j--){                    //temp
            flag+=(str1[j]-'0')*(str2[i]-'0');
            temp.push_back('0'+(flag%10));
            flag/=10;
        }
        if(flag) temp.push_back('0'+flag);              //如果最高位还有进位
        reverse(temp.begin(),temp.end());
        ans=Add(ans,temp);                              //将计算结果累加到最终的结果上
    }
    if(negative) ans="-"+ans;                           //处理结果的正负号
    return ans;
}
string Div(string str1, string str2){
    //处理除数为0的情况和被除数为0的情况
    if(CheckZero(str2)) return "The divisor cannot be zero!";
    else if(CheckZero(str1)) return "0.000000";
 
    int negative=0,negastr1=0,negastr2=0;               //定正负
    if(CheckNegative(str1)){                            //确定正负号标记,并且去掉-
        negastr1=1; str1=str1.substr(1,str1.size()-1);
    }
    if(CheckNegative(str2)){
        negastr2=1; str2=str2.substr(1,str2.size()-1);
    }
    negative=negastr1^negastr2;                         //异或运算确定结果的正负号
 
    int point=0;                                        //结果是否为纯小数
    if(Lower(str1,str2)) point=1;                       //如果str1小于str2,则计算为纯小数
    string ans;                                         //计算结果
    str1+=string(6,'0');                                //补足6个0,用于计算小数位
 
    int size1=str1.size(),size2=str2.size();
    int i=size2-1;                                      //商第一位的位置
    string temp=str1.substr(0,i);                       //从str1上取size2-1个字符
    for(i;i<size1;i++){
        temp+=str1[i];                                  //从后边拿出一位,预先处理可以防止结尾处越界
        int cnt=0;                                      //当前位的商,也就是temp中包含了多少个str2,使用减法                                          //如果temp不为0,则计算商
        while(Lower(str2,temp)||temp==str2){            //如果当前位商不为0,则计算商
            temp=Sub(temp,str2);
            cnt++;
        }
        if(temp=="0") temp.clear();                     //如果某次计算结果为0,则清空,避免0的堆积,比如111000 111
        ans.push_back('0'+cnt);                         //保存商
    }
    i=0;
    while(ans[i]=='0') i++;
    ans=ans.substr(i,ans.size()-i);                     //去除前导0
    if(point){                                          //如果是纯小数,补足6位并添加小数点
        int len=6-ans.size();
        ans="0."+string(len,'0')+ans;
    }
    else ans.insert((ans.end()-6),'.');                 //如果不是小数,则只需要插入小数点       
    if(negative) ans="-"+ans;                           //最后一步骤,如果是负数带上负号
    return ans;
}
bool Lower(string str1, string str2){                   //长度长的一定大(这里假设除了0以外,都没有前导0),长度相等则字典序小的数字更小
    return str1.size()<str2.size()||(str1.size()==str2.size()&&str1<str2);
}
bool CheckZero(const string &str){      //检查是否等于0
    int size=str.size();                //如果全是0则为0,这里假设不会有带符号的+00000或者-00000作为输入
    for(int i=0;i<size;i++)
        if(str[i]!='0') return false;
    return true;
}
bool CheckNegative(const string &str){  //检查是否为负数
    return str[0]=='-';
}
void ShowMenu(){
    cout<<"请选择要进行的大数运算:\n"
        <<"a) 加法          b) 减法\n"
        <<"c) 乘法          d) 除法\n"
        <<"q) 退出\n"
        <<"请输入你的选择: ";
}
void ShowMenu(char choice){
    cout<<"请输入要计算的两个数字";
    switch(choice){
        case 'a':cout<<"(仅支持非负整数加法计算): "<<endl;break;
        case 'b':cout<<"(仅支持非负整数减法计算): "<<endl;break;
        case 'c':cout<<"(仅支持整数乘法计算): "<<endl;break;
        case 'd':cout<<"(仅支持整数除法计算,计算结果保留6位小数,之后的直接舍弃): "<<endl;break;
    }
}

付録、さらなる研究と理解

https://blog.csdn.net/weixin_44668898/article/details/96763177

https://blog.csdn.net/wyqxii/article/details/131965735

おすすめ

転載: blog.csdn.net/cnds123/article/details/132858897