- 高精度
- 笔记
- HighAccuracy_acwing.cpp
- HighAccuracy_oiwiki.cpp
- HighAccuracy_additional.cpp
- 知识点&例题
- 高精度加法
- 乘法
- 高精度乘低精度
- 高精度乘高精度
- P1303 A*B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 模板题
- re了,数组大小的问题,不懂怎么算要开多大
- P1303 A*B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 高精度除以低精度
- 文章
- acwing模板【推荐】
- oiwiki模板
- 力扣模板
- 字符串相加 - 字符串相加 - 力扣(LeetCode)
没有其他的了,力扣几乎没有高精度的题
- 字符串相加 - 字符串相加 - 力扣(LeetCode)
- 笔记
/*HighAccuracy_oiwiki.cpp*/
#include <cstdio>
#include <cstring>
static const int LEN = 10005;// 定义静态的长度变量LEN
int a[LEN], b[LEN], c[LEN], d[LEN];// 定义高精度数组
void clear(int a[]) {// 高精度数组清零操作
for (int i = 0; i < LEN; ++i) a[i] = 0;
}
bool cmp(int a[], int b[])// 高精度比较函数
{
for (int i = LEN - 1; i >= 0; --i){
if (a[i] > b[i]) return true;
if (a[i] < b[i]) return false;
}
return true;
}
void read(int a[]) {// 输入高精度数
static char s[LEN + 1];
scanf("%s", s);
clear(a);
int len = strlen(s);
for (int i = 0; i < len; ++i) a[len - i - 1] = s[i] - '0';//实现了倒序,即个十百千万0000···
}
void print(int a[]) {// 输出高精度数
int i;
for (i = LEN - 1; i >= 1; --i)//去掉后面的零,即 个十百千万0000··· 变成 个十百千万
if (a[i] != 0) break;
for (; i >= 0; --i) putchar(a[i] + '0');
putchar('\n');
}
void add(int a[], int b[], int c[]) {// 高精度加法(高精度加高精度)
clear(c);
for (int i = 0; i < LEN - 1; ++i) {
c[i] += a[i] + b[i];
if (c[i] >= 10) {
c[i + 1] += 1;
c[i] -= 10;
}
}
}
void sub(int a[], int b[], int c[]) {// 高精度减法(高精度减高精度)
clear(c);
for (int i = 0; i < LEN - 1; ++i) {
c[i] += a[i] - b[i];
if (c[i] < 0) {
c[i + 1] -= 1;
c[i] += 10;
}
}
}
void mul(int a[], int b[], int c[]) {// 高精度乘法(高精度乘以高精度)
clear(c);
for (int i = 0; i < LEN - 1; ++i) {
for (int j = 0; j <= i; ++j) c[i] += a[j] * b[i - j];
if (c[i] >= 10) {
c[i + 1] += c[i] / 10;
c[i] %= 10;
}
}
}
inline bool greater_eq(int a[], int b[], int last_dg, int len) {// 判断大小数组(具体原理请参照OIwiki)
if (a[last_dg + len] != 0) return true;
for (int i = len - 1; i >= 0; --i) {
if (a[last_dg + i] > b[i]) return true;
if (a[last_dg + i] < b[i]) return false;
}
return true;
}
void div(int a[], int b[], int c[], int d[]) {// 高精度除法(高精度除以高精度)
clear(c);
clear(d);
int la, lb;
for (la = LEN - 1; la > 0; --la)
if (a[la - 1] != 0) break;
for (lb = LEN - 1; lb > 0; --lb)
if (b[lb - 1] != 0) break;
if (lb == 0) {
puts("> <");
return;
}
for (int i = 0; i < la; ++i) d[i] = a[i];
for (int i = la - lb; i >= 0; --i) {
while (greater_eq(d, b, i, lb)) {
for (int j = 0; j < lb; ++j) {
d[i + j] -= b[j];
if (d[i + j] < 0) {
d[i + j + 1] -= 1;
d[i + j] += 10;
}
}
c[i] += 1;
}
}
}
int main() {
freopen("luogu_in.txt","r",stdin); // 文件输入
freopen("luogu_out.txt","w",stdout);// 文件输出
read(a);
char op[4];
scanf("%s", op);
read(b);
switch (op[0]) {
case '+':
add(a, b, c);
print(c);
break;
case '-':
if(cmp(a, b)) sub(a, b, c);
else{
printf("-");
sub(b, a, c);
}
print(c);
break;
case '*':
mul(a, b, c);
print(c);
break;
case '/':
div(a, b, c, d);
print(c);
print(d);
break;
default:
puts("> <");
}
return 0;
}
/*HighAccuracy_acwing.cpp*/
#include<bits/stdc++.h>
using namespace std;
bool sub_plus(vector<int> &a, vector<int> &b){//0表示负数,1表示正数
if(a.size()<b.size()) return 0;
if(a.size()==b.size()){
for(int i = 0; i<a.size(); i++){
if(a[i]<b[i]){
return 0;
}
}
}
return 1;
}
vector<int> add(vector<int> &A, vector<int> &B){ //正序输入两个vector类型的“数”
if (A.size() < B.size()) return add(B, A); //使得A数组是最大的
//如果未反转,在if下面加reverse,不能在if上面加reverse,否者二次反转,等于没有反转
reverse(A.begin(),A.end()); //反转数组,变成个十百千万···
reverse(B.begin(),B.end());
vector<int> c; //初始化答案数组
int t = 0;
for (int i = 0; i < A.size(); i ++ ){
t += A[i];
if (i < B.size()) t += B[i]; //如果B还有数字
c.push_back(t % 10);
t /= 10;
}
if (t) c.push_back(t);//最后一次加法可能还有进位的数,把最高位补上
while (c.size() > 1 && c.back() == 0) c.pop_back();//处理前导零
reverse(c.begin(), c.end());
return c;
}
// C = A - B, 满足A >= B, A >= 0, B >= 0
vector<int> sub(vector<int> &A, vector<int> &B){
reverse(A.begin(),A.end()); //反转数组,变成个十百千万···
reverse(B.begin(),B.end());
vector<int> C;
for (int i = 0, t = 0; i < A.size(); i++ ){
t = A[i] - t;
if (i < B.size()) t -= B[i];
C.push_back((t + 10) % 10);//无论如何,先向高位借1
if (t < 0) t = 1;//t是负数,说明是真的借1了
else t = 0;//t是非负数,说明不用借1
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
reverse(C.begin(), C.end());
return C;
}
//不清楚c数组开多大
vector<int> multwo(vector<int> &a, vector<int> &b){
if(a.size()<b.size()) return multwo(b,a);
vector<int> c(1000001,0); //初始化答案数组(不知道开多大)
reverse(a.begin(), a.end()); //反转数组,变成个十百千万···
reverse(b.begin(), b.end());
int t = 0;
for(int i = 0; i<b.size(); i++){ //b数组数少,是外循环
for(int j = 0; j<a.size() || t; j++){ //a数组数多,是内循环
if(j<a.size()) t += a[j]*b[i];
c[j+i] += t % 10;
t /= 10;
}
}
//处理c数组的进位
for(int i = 0; i<a.size()*b.size(); i++){ //无论数字如何大,数位也不会大于两个乘数的和
if(c[i]>9){
c[i+1]+=c[i]/10;
c[i]%=10;
}
}
while (c.size() > 1 && c.back() == 0) c.pop_back(); //末尾可能是0,都要去掉(我感觉是多余的,不可能有这种情况)(难道是处理b==0?)
reverse(c.begin(), c.end());
return c;
}
/*除法*/
// A / b = C ... r, A >= 0, b > 0
vector<int> div(vector<int> &A, int b, int &r){
reverse(A.begin(), A.end());
vector<int> C;
r = 0;
for (int i = A.size() - 1; i >= 0; i -- ){ //从右向左
r = r * 10 + A[i]; //高位除不尽的数,留给低位
C.push_back(r / b);
r %= b;
}//高位在左,低位在右
reverse(C.begin(), C.end());//低位在左,高位在右
while (C.size() > 1 && C.back() == 0) C.pop_back();
reverse(C.begin(), C.end());//高位在左,低位在右
return C;
}
int main(){
string in; getline(cin,in);
vector<int> a;
vector<int> b;
vector<int> c;
char f;
int i;
for(i = 0; i<in.size(); i++){
if(in[i]!=' ') a.push_back(in[i]-'0');
else break;
}
i++;
f = in[i];
i+=2;
for(i; i<in.size(); i++) b.push_back(in[i]-'0');
switch (f) {
case '+':
c = add(a,b);
break;
case '-':
//增加负号
if(!sub_plus(a,b)){
printf("-");
c = sub(b,a);
}
else c = sub(a,b);
break;
case '*':
c = multwo(a,b);
break;
case '/':
int bb = b[0]; int d;
c = div(a,bb,d);
break;
// default:
// puts("> <");
}
for(int i = 0; i<c.size(); i++) printf("%d", c[i]);
return 0;
}
/*
*/
/*HighAccuracy_additional.cpp*/
#include<bits/stdc++.h>
using namespace std;
// C = A + B, A >= 0, B >= 0
//这里不加&,就可以避免改变了原来的a,b数组,使得a,b数组可以重复利用
vector<int> add(vector<int> A, vector<int> B){ //正序输入两个vector类型的“数”
if (A.size() < B.size()) return add(B, A); //使得A数组是最大的
//如果未反转,在if下面加reverse,不能在if上面加reverse,否者二次反转,等于没有反转
reverse(A.begin(),A.end()); //反转数组,变成个十百千万···
reverse(B.begin(),B.end());
vector<int> c; //初始化答案数组
int t = 0;
for (int i = 0; i < A.size(); i ++ ){
t += A[i];
if (i < B.size()) t += B[i]; //如果B还有数字
c.push_back(t % 10);
t /= 10;
}
if (t) c.push_back(t);//最后一次加法可能还有进位的数,把最高位补上
reverse(c.begin(), c.end());
return c;
}
string add(string a, string b){
if(a.size()<b.size()) return add(b,a);
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
int t = 0;
string c;
for(int i = 0; i<a.size(); i++){
t += a[i] - '0';
if(i<b.size()) t+=b[i] - '0';
c.push_back(t%10 + '0');
t /= 10;
}
if(t) c.push_back(t + '0');
reverse(c.begin(), c.end());
return c;
}
// C = A - B, 满足A >= B, A >= 0, B >= 0
vector<int> sub(vector<int> A, vector<int> B){
reverse(A.begin(),A.end()); //反转数组,变成个十百千万···
reverse(B.begin(),B.end());
vector<int> C;
for (int i = 0, t = 0; i < A.size(); i++ ){
t = A[i] - t;
if (i < B.size()) t -= B[i];
C.push_back((t + 10) % 10);//无论如何,先向高位借1
if (t < 0) t = 1;//t是负数,说明是真的借1了
else t = 0;//t是非负数,说明不用借1
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
reverse(C.begin(), C.end());
return C;
}
/*高精度乘低精度 —— 模板题*/
// C = A * b, A >= 0, b >= 0
vector<int> mul(vector<int> A, int b){ //输入正序的高精度A和低精度b
vector<int> C; //初始化答案数组
reverse(A.begin(),A.end()); //反转数组,变成个十百千万···
int t = 0;
for (int i = 0; i < A.size() || t; i++ ){ //A数组还有数 或 t还有数
if (i < A.size()) t += A[i] * b; //如果 A数组还有数
C.push_back(t % 10);
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back(); //末尾可能是0,都要去掉(我感觉是多余的,不可能有这种情况)(难道是处理b==0?)
reverse(C.begin(),C.end()); //反转数组,恢复正序
return C;
}
string mul(string a, int b){
reverse(a.begin(), a.end());
string c;
int t = 0;
for(int i = 0; i<a.size() || t; i++){
if(i<a.size()) t += (a[i] - '0') * b;
c.push_back(t%10 + '0');
t /= 10;
}
while(c.size()>1 && c.back() == 0)c.pop_back();
reverse(c.begin(), c.end());
return c;
}
//不清楚c数组开多大
vector<int> multwo(vector<int> a, vector<int> b){
if(a.size()<b.size()) return multwo(b,a);
vector<int> c(10001,0); //初始化答案数组(不知道开多大)
reverse(a.begin(), a.end()); //反转数组,变成个十百千万···
reverse(b.begin(), b.end());
int t = 0;
for(int i = 0; i<b.size(); i++){ //b数组数少,是外循环
for(int j = 0; j<a.size() || t; j++){ //a数组数多,是内循环
if(j<a.size()) t += a[j]*b[i];
c[j+i] += t % 10;
t /= 10;
}
}
//处理c数组的进位
for(int i = 0; i<a.size()*b.size(); i++){ //无论数字如何大,数位也不会大于两个乘数的和
if(c[i]>9){
c[i+1]+=c[i]/10;
c[i]%=10;
}
}
while (c.size() > 1 && c.back() == 0) c.pop_back(); //末尾可能是0,都要去掉(我感觉是多余的,不可能有这种情况)(难道是处理b==0?)
reverse(c.begin(), c.end());
return c;
}
/*除法*/
// A / b = C ... r, A >= 0, b > 0
vector<int> div(vector<int> &A, int b, int &r){
reverse(A.begin(), A.end());
vector<int> C;
r = 0;
for (int i = A.size() - 1; i >= 0; i -- ){ //从右向左
r = r * 10 + A[i]; //高位除不尽的数,留给低位
C.push_back(r / b);
r %= b;
}//高位在左,低位在右
reverse(C.begin(), C.end());//低位在左,高位在右
while (C.size() > 1 && C.back() == 0) C.pop_back();
reverse(C.begin(), C.end());//高位在左,低位在右
return C;
}
int main(){
//加法
vector<int> addint1 = {1,2,3,4,5,6,7,8,9};
vector<int> addint2 = {9,8,7,6,5,4,3,2,1,0};
vector<int> addint3 = add(addint1,addint2);
for(int i = 0;i<addint3.size(); i++) cout<<addint3[i];
printf("\n");
//加法
string addstr1 = {"123456789"};
string addstr2 = {"9876543210"};
string addstr3 = add(addstr1,addstr2);
cout<< addstr3 <<endl;
//减法
vector<int> subint1 = {9,8,7,6,5,4,3,2,1,0};
vector<int> subint2 = {9,0,7,0,5,0,3,0,1,0};
vector<int> subint3 = sub(subint1,subint2);
for(int i = 0;i<subint3.size(); i++) cout<<subint3[i];
printf("\n");
//乘法(高精度*低精度)
vector<int> mulint1 = {9,0,0,8,0,0,7,0,0,6,0,0,5,0,0,4,0,0,3,0,0,2,0,0,1};
int mulint2 = 9;
vector<int> mulint3 = mul(mulint1,mulint2);
for(int i = 0;i<mulint3.size(); i++) cout<<mulint3[i];
printf("\n");
//乘法(高精度*低精度)
string mulstr1 = "9008007006005004003002001";
int mulstr2 = 9;
cout<<mul(mulstr1,mulstr2)<<endl;
//乘法(高精度*高精度)
vector<int> multwo1 = {1,2,3,4,5,6,7,8,9};
vector<int> multwo2 = {1,2,3,4,5,6,7,8,9};
vector<int> multwo3 = multwo(multwo1,multwo2);
for(int i = 0;i<multwo3.size(); i++) cout<<multwo3[i];
printf("\n");
//除法(高精度/低精度)
vector<int> divint1 = {8,1,0,7,2,0,6,3,0,5,4,0,4,5,0,3,6,0,2,7,0,1,8,0,0,9};
int divint2 = 9;
int divintr = 0;
vector<int> divint3 = div(divint1,divint2,divintr);
for(int i = 0;i<divint3.size(); i++) cout<<divint3[i];
printf("\n");
return 0;
}