前言:
由于long long类型也会有上限,所以引入了高精度的概念,其实就是把其当成字符串放入数组进行处理。【已经通过测试】
关于高精度加减乘法:
注意对位细节,跟平常的加减乘除一样,从最后往前进行相加,然后保存超出10的部分。所以我们需要创数组把我们输入的字符串从后往前进行遍历.直接上代码
#include <iostream>
using namespace std;
#include <string>
#include <cstring>
#define N 105000
int a[N], b[N], c[N];
string ss1, ss2;
int main(void)
{
cin >> ss1 >> ss2;
memset(a, 0, sizeof(a));//数组清零
memset(b, 0, sizeof(a));
memset(c, 0, sizeof(a));
int sz1 = ss1.size(), sz2 = ss2.size();
for (int i(0); i < sz1; i++)a[sz1 - i] = ss1[i] - '0'; //相当于逆换。
for (int i(0); i < sz2; i++)b[sz2 - i] = ss2[i] - '0';
......
return 0;
}
这就是交换后的结果.-------->除法跟加减乘不一样(待会在解释)[加减乘都是这模板可以直接套]
1.高精度加法(最简单)
直接对位相加,当某位超过10直接%10-->然后下一位直接对加相应多出的数即可
for(int i(1);i<cz;i++)//cz的长度为max(sz1,sz2)+1;
{
c[i]=n1[i]+n2[i]+x;
x=c[i]/10; //其实这里也可以加一个条件 当..x>=10时才执行
c[i]%=10; //%10保存<10的数
}
c[i]=x;//保存最后的进位;
2.高精度减法
减法会比加法多一个判定条件 -----> 当输入的ss1<ss2时 我们交换一下 这样就会保持 ss1>=ss2 因为相减为 负数后面比较麻烦处理 我们 直接先判断 率先加一个负号 即可.
先上判定代码:
//先判断ss1是否比ss2小,如果小就交换两则的顺序
if ((ss1.size()<ss2.size()) || (ss1.size() ==ss2.size() && ss1<ss2)) {
swap(ss1, ss2); //交换
cout << "-";
}//并率先输出一个负号}
模板:
int max_c = max(sz1, sz2); //这里与加法不同没有+1,因为减法不存在最后多一位的情况
for (int i(1); i <= max_c; i++) {
if (a[i] < b[i]) {
a[i + 1] --; //如果a<b我们直接向下一位借位,然后本位加10.
a[i] += 10;}
c[i] = a[i] - b[i];
}
3.高精度乘法
自己在本子上列一下:
图片来源:B站-(自己难得写,直接搬运一下别人的 )
看对应关系,直接上代码:(因为对应相加 又因为采取二重循环,所有c下标对应关系为:i+j-1(i=j=1开始)-------<>
for (int i = 1; i <= sz1; i++) {
for (int j=1; j <= sz2; j++) {
c[i + j - 1] += a[i] * b[j]; //看不懂,可以直接记模板
c[i + j] += c[i + j - 1] / 10;
c[i + j - 1] %= 10;
}
}
4.高精度除法
4.1(高精度/低精度)
基本运算大体一致,只是直接按照顺序存储不再用逆置.
先上代码:
算了 还是找了点对应资料 ............................................................................................................
图片来源:B站-
模板:
for(int i(0);i<=sz;i++){ //sz为输入高精度数的长度
b[i]=(x*10+a[i])/10;
x=(x*10+a[i])%10;
}
输出格式(注意0000!!!!!!!)
while(b[max_c] == 0 && max_c <la)max_c++; //max_c=1
for (int i = max_c; i <=la; i++)
cout << b[i];
cout << endl;
4.高精度/高精度
不好解释,直接看代码(模板也不好写hahha)----><------
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
#define N 100005
string ss1, ss2;
int a[N], b[N], c[N],temp[N]; //保存字符数组内容;
void temp_create(int temp[], int b[], int n) {
int i = 1;
for (i;i<=b[0]; i++) {
temp[n + i - 1] = b[i];
}
temp[0] = n+b[0]-1;//
}
int cmp(int a[], int temp[]) {
if (a[0] > temp[0])return 1;
if (a[0] < temp[0])return -1;
for (int i(a[0]); i > 0; i--) {
if (a[i] > temp[i])return 1;
if (a[i] < temp[i])return -1;
}
return 0;
}
void start_sub(int a[], int temp[]) {
int max_sub = max(a[0], temp[0]);
for (int i(1); i <= max_sub; i++) {
if (a[i] < temp[i]) {
a[i] += 10;
a[i + 1]--;
}
a[i] = a[i] - temp[i];
}
//删除前缀0;
while (a[a[0]]==0&&a[0]>0)a[0]--;
}
void print(int num[]) {
if (num[0] == 0) {
cout << 0;
return;
}
for (int i(num[0]); i > 0; i--) {
cout << num[i];
}
return;
}
int main(void)
{
cin >> ss1 >> ss2; //首先输入除数和被除数放入字符数组
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));
a[0] = ss1.size(), b[0] = ss2.size(); //判定大小放入首地址
c[0] = a[0] - b[0] + 1;//按照规律可得输出的大小最大为s1长-s2长+1;
for (int i(0); i < a[0]; i++) a[a[0] - i] = ss1[i] - '0';
for (int i(0); i < b[0]; i++) b[b[0] - i] = ss2[i] - '0';
for (int i(c[0]); i > 0; i--) {
memset(temp, 0, sizeof(temp)); //每次执行清空一次
temp_create(temp,b,i );
while (cmp(a, temp) >= 0) {
c[i]++; //对应位数进行++
start_sub(a, temp); //进行高精度减法
}
}
while (c[c[0]] == 0 && c[0] > 0)c[0]--; //删除前缀0
print(c);//输出结果
cout << " ";
print(a);//输出余数
return 0;
}
5.输出部分
一定记得消除多余0!
(这里适合:加减乘 ,除法在上面)
while(c[max_c] == 0 && max_c > 1)max_c--; //max_c长度看情况而定
//加减直接对应i 而乘法对应 sz1+sz2(ss1\ss2总长)
for (int i = max_c; i > 0; i--)
cout << c[i];
cout << endl;



519

被折叠的 条评论
为什么被折叠?



