能力有限,除法就不写了。。
关于大数
在C/C++语言编写过程中,数据并不是可以一直增长下去,数据极限大小由数据类型本身所占字节所决定,而一个字节大小为8比特,int类型占4个字节,每个类型的首位01所代表的是正负值,于是,int类型的范围为 -231 ~ 231-1,无符号类型的int(unsigned int)由于不需要表示正负,范围会大一些 0 ~ 232-1,而若是我们想表达更大的数据,就不能再使用普通的int或其他的数据类型,我们需要使用int类型的数组,将每一位数字看成字符将它一位一位存进这个数组,这样一来,从理论上看,我们就可以无限制的存储一位数字了
思路
对两个数组进行计算,所做的事就是模拟小学时的竖式计算
562
+ 469
________
1031
将每一位进位或退位储存到一个值中在进行下一位计算时,便使用这个值进行计算
大数加法
由这一步实现进位与储存
C.push_back(flag % 10);
flag /= 10;
完整
#include<bits/stdc++.h>
using namespace std;
string fir, sec;
vector<int>sum(vector<int> A, vector<int> B)
{
vector<int> C;
int flag = 0; //最重要的一个变量
for (int i = 0; i < A.size() || i < B.size(); i++) { //A和B的长度可以不一样,所以小于他们最长的一个
if (i < A.size()) flag += A[i]; //只有当A和B还有位的时候,才加
if (i < B.size()) flag += B[i];
C.push_back(flag % 10); //由于可能进位,只存个位
flag /= 10; //进位
}
if (flag) C.push_back(flag); //若flag还有余下的,将这个值压入C中
return C;
}
int main()
{
vector<int> A, B, C;
cin >> fir >> sec;
for (int i = fir.size() - 1; i >= 0; i--) A.push_back(fir[i] - '0'); //将每一位数字先存进容器中,倒序存,方便后续压入
for (int i = sec.size() - 1; i >= 0; i--) B.push_back(sec[i] - '0');
C = sum(A, B); //加了
for (int i = C.size() - 1; i >= 0; i--) cout << C[i]; //倒序输出
return 0; //华丽的结束
}
大数减法
减法相较加法,不同的地方在于是借位而不是进位,而较为繁琐的地方也在于比较两数谁更大,为了简便,只对两数都是正数的情况进行讨论
比较两数大小
bool cmp(vector<int> A, vector<int> B)
{
if (A。size() != B.size()) return A.size() > B.size();
for (int i = A.size(); i >= 0; i--) {
if (A[i] != B[i]) return A[i] > B[i];
}
return true;
}
借位
C.push_back((flag + 10) % 10);
if (flag < 0) flag = 1;
else flag = 0;
完整
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
using namespace std;
string fir, sec;
bool cmp(vector<int> &A, vector<int> &B)
{
/*if( A.size() > B.size() ){
return true;
}
else if(A.size() < B.size()){
return false;
}*/
if (A.size() != B.size()) return A.size() > B.size(); //如果A和B的长度不相等,返回A是否长于B
for (int i = A.size() - 1; i >= 0; i--) {
if (A[i] != B[i]) return A[i] > B[i]; //如果A[i]对应的值大于或等于B[i],返回A大于B
}
return true;
}
vector<int> sub(vector<int> &A, vector<int> &B)
{
vector<int> C;
int flag = 0; //同加法中flag的作用
for (int i = 0; i < A.size(); i++) {
flag = A[i] - flag; //由于借位操作在flag上完成,所以由A[i] - flag
if (i < B.size()) flag -= B[i];
C.push_back((flag + 10) % 10); //这一步免去判断flag是否小于0,直接使用flag + 10来取余,若flag大于0,无影响,若flag小于0,通过这一步实现借位操作(学长讲的即是www)
if (flag < 0) flag = 1; //如果flag小于0,说明上一步有过借位,令flag = 1,用于A[i]减
else flag = 0; //如果没有借位,flag = 0
}
while (C.back() == 0 && C.size() > 1) C.pop_back();
return C;
}
int main()
{
int flag = 1; //正负的标记
vector<int> A, B, C;
cin >> fir >> sec;
for (int i = fir.size() - 1; i >= 0; i--) A.push_back(fir[i] - '0'); //同样先压入
for (int i = sec.size() - 1; i >= 0; i--) B.push_back(sec[i] - '0');
if (cmp(A, B)) { //比较fir和sec的大小,如果A大,用A做被减数
C = sub(A, B);
}
else {
C = sub(B, A); flag = -1;
}
if (flag == -1) cout << "-"; //如果flag为-1,结果为负数
for (int i = C.size() - 1; i >= 0; i--) cout << C[i];
return 0;
}
大数乘法
乘法竖式计算中,从某一位开始乘回到哪一位做加法是关键(没有用vector…因为那时不会)
#include<bits/stdc++.h>
using namespace std;
#define maxn 10000
int flag, ans[maxn];
int main()
{
int n, flag1 = 0, flag2 = 0;
string fir, sec;
cin >> fir >> sec;
int lenu, lend;
lenu = fir.length();
lend = sec.length(); //lend是下面的数,这个数与回退有关
for (int i = lend - 1; i >= 0; i--) {
n = lend - i - 1; //回退到对应位置
for (int j = lenu - 1; j >= 0; j--) {
ans[n] = (fir[j] - '0') * (sec[i] - '0') + ans[n];
flag = ans[n] / 10; //进了多少位
ans[n] %= 10;
n++;
ans[n] = flag + ans[n]; //将进的位加进下一个
}
}
flag = 0; //flag作用改变,为判断前置0
for (n + 1; n >= 0; n--) {
if (ans[n] != 0) flag = 1; //去掉前置0
if (flag == 1) cout << ans[n];
}
if (fir == "0" || sec == "0") cout << "0"; //这时由于将前导0全部去掉,没有答案,所以单独输出
return 0;
}
总结
思路不复杂,就是模拟竖式,但有一些小细节需要注意,比如倒序存入带来的便利和注意点,正负号判断等等,就不写了。。
第一次写文,写的不对请告诉我。。望海涵 /doge。