本文主要是介绍高精度|大数加减乘,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、大数加法
1.反转法 (不开动态数组存)
#include<bits/stdc++.h>
using namespace std;
string add(string s1,string s2){if(s1.length() < s2.length() ) swap(s1,s2);reverse(s1.begin(),s1.end());reverse(s2.begin(),s2.end());int carry = 0;for(int i = 0 ; i < s2.length() ; i++){int sum = (s1[i] - '0') + (s2[i] - '0') + carry;s1[i] = sum%10 + '0';carry = sum / 10;}for(int i = s2.length() ; i < s1.length() ; i++){int sum = s1[i]-'0' + carry;s1[i] = sum % 10 + '0';carry = sum /10;}if(carry) {s1.push_back(carry + '0');}reverse(s1.begin() , s1.end());return s1.empty() ? 0 : s1;
}
int main(){string num1,num2;cin>>num1>>num2;string num = add(num1,num2);cout<<num<<endl;
}
2.开数组存
#include<bits/stdc++.h>
using namespace std;
string add(string s1,string s2){int len1 = s1.length() - 1;int len2 = s2.length() - 1;int carry = 0;string result;//动态数组保存答案 vector<char> result;while(len1 >=0 || len2 >=0 ){int n1 = len1 >=0 ? (s1[len1--] - '0') : 0;//大端方式(从个位计算) int n2 = len2 >=0 ? (s2[len2--] - '0') : 0; int sum = n1 + n2 + carry;carry = sum /10;result.push_back(sum%10+'0');}//始终对进位要处理 if(carry > 0 ){result.push_back(carry + '0');}reverse(result.begin(),result.end());//调用vector数组即能够反转,也能转化为字符串 //string r1(result.rbegin() , result.rend());return r1;
}
int main(){string num1,num2;cin>>num1>>num2;string num = add(num1,num2);cout<<num<<endl;
}
二、大数减法
加负号 + 交换两数
1.数字1.length() < 数字2.length();
2.两数字长度相同,但数字1 < 数字2
#include<bits/stdc++.h>
using namespace std;string subtract(string num1,string num2){if(num1.size() < num2.size() || (num1.size() == num2.size() && num1 < num2)){return "-" + subtract(num2,num1);//交换两个数并返回负数形式。 }string result = " ";int len1 = num1.size()-1;int len2 = num2.size()-1;int borrow = 0;//计算 while(len1 >= 0 || len2 >= 0){int n1 =len1 >= 0 ? num1[len1--]-'0':0;int n2 = len2 >= 0 ? num2[len2--]-'0':0;int sub = n1 - n2 - borrow;//个位减法后观察是否借位 if(sub<0){sub+= 10;borrow = 1;}else borrow = 0;//将结果保存 result.push_back(sub+'0');} //去除前导零 while(result.size() >1 && result.back() =='0') result.pop_back();//反转 reverse(result.begin(),result.end());return result;
}
int main(){string num1,num2;cin>>num1>>num2;string num = subtract(num1,num2);cout<<num<<endl;
}
总结:
大数加减法主要使用借位和进位的方式,并且都可以采用string进行存储,随后反转结果,只不过减法,1. 交换两数 + 要加负号,2.要对多余的前导零(直接丢掉)pop_back()
三、大数乘法
两种思路在for循环不同,第一个好理解也好模拟,但是注意加法的位置**(错位相加)**
#include<bits/stdc++.h>
#define N 1001
using namespace std;
string multiply(string num1,string num2){if(num1 == "0" || num2 == "0") return "0";reverse(num1.begin(), num1.end());reverse(num2.begin(),num2.end());int len1 = num1.size();int len2 = num2.size();vector<int> result(len1 + len2,0);for (int i = 0; i < len1; ++i) {for (int j = 0; j < len2; ++j) {//重点:之前的本位 + 该位结果 = 现在本位result[i + j] += (num1[i] - '0') * (num2[j] - '0'); // 直接累加到结果的相应位置//求进位result[i + j + 1] += result[i + j] / 10; // 处理进位//更新本位result[i + j] %= 10; // 更新当前位的值}}string strResult;for(int i = result.size() - 1 ; i >= 0 ;--i){//去除前导零 if(strResult.empty() && result[i] == 0) continue;strResult.push_back(result[i] +'0');}return strResult.empty() ? "0": strResult;
}
int main(){string num1,num2;cin>>num1>>num2;string result = multiply(num1,num2);cout<<result<<endl;
}
#include<bits/stdc++.h>
using namespace std;string subtract(string num1,string num2){int len1 = num1.size();int len2 = num2.size();vector<int> result(len1+len2,0);//这个不好理解啊for(int i = len1-1;i>=0;i--){for(int j =len2-1 ; j>=0 ;j--){int mul = (num1[i] - '0') * (num2[j] -'0');int sum = result[i+j+1] + mul;result[i+j+1] = sum%10;//保存个位数 result[i+j] += sum /10;//进位 }}string strResult;//忽略前导零存数字 for(int digit : result){if(!(strResult.empty() && digit == 0)){strResult.push_back(digit + '0');}} return strResult.empty() ? "0":strResult;
}int main(){string num1,num2;cin>>num1>>num2;string num = subtract(num1,num2);cout<<num<<endl;
}
总结
大数乘法注意1. 使用动态数组存
2.去除前导零(遍历去除)
当然洛谷里面的这个题解看起来更简单易懂
四、大数除法
结合加法减法乘法进行操作,比较复杂
这篇关于高精度|大数加减乘的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!