高精度

high-precision

高精度加法

加法原理

  • 从右向左,逐位相加;
  • 从右向左,逐位进位;

思路

  • 用两个字符串读入高精度整数;
  • 由于要从右向左计算,从右向左进位, 因此将每一位逆序存入2个整数数组;
  • 从左向右逐位做计算,逐位进位;
  • 逆序输出计算结果;

例题讲解

原题链接

题目描述

计算 a + b 的值,a,b 皆为不超过240 位的非负整数。

输入

两个正整数,每行一个。

输出

一个数,代表两个整数的和。

answer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<iostream>
using namespace std;

int main(){
string s1,s2; // 存放高精度数
int a[250]={0},b[250]={0},c[251]={0};

// 将高精度整数存入字符串
cin >> s1 >> s2;

// 将两个高精度整数逆序存入ab两个整数数组
for(int i=0;i<s1.size();i++){
a[s1.size()-i-1] = s1[i] - '0';
}
for(int i=0;i<s2.size();i++){
b[s2.size()-i-1] = s2[i] - '0';
}

//加法的次数,取决于两个整数的较长的字符串
int len = s1.size();
if(len < s2.size())
len = s2.size();

// 将两个数从左向右,逐位求和进位,存入数组c
for(int i=0;i < len; i++){
c[i] += a[i] + b[i];
if(c[i] > 9){
c[i+1] = c[i]/10;
c[i] %= 10;
}
}

// 逆序输出
if(c[len] >0)
len++;
for(int i=len-1;i>=0;i--){
cout << c[i];
}

}

高精度减法

思路

  • 判断正负,如果 s1 < s2 ,结果为负,交互s1 s2
  • 将两个字符串,逆序存入2个整数输出
  • 从左至右,逐位相减,不够借位
  • 从右向左,逆序输出

source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<iostream>
using namespace std;

int main(){
string s1,s2; // 存放高精度数
char f = '+'; // 表示结果正负
int a[250]={0},b[250]={0},c[250]={0};

// 将高精度整数存入字符串
cin >> s1 >> s2;

if(s1.size() < s2.size() || s1.size() == s2.size() && s1 < s2){
f = '-';
swap(s1,s2);
}

// 将两个高精度整数逆序存入ab两个整数数组
for(int i=0;i<s1.size();i++){
a[s1.size()-i-1] = s1[i] - '0';
}
for(int i=0;i<s2.size();i++){
b[s2.size()-i-1] = s2[i] - '0';
}

// 逐位相减
int len = s1.size();
for(int i=0;i<len;i++){
// 如果不够减
if(a[i]<b[i]){
a[i+1]--;
a[i] += 10;
}
c[i] = a[i] - b[i];
}

if(f=='-')
cout << f;

// 输出
int p; //记录第一个非0数下标
for(int i=len-1;i >= 0;i--){
if(c[i] != 0){
p = i;
break;
}
}
for(int i=p;i>=0;i--){
cout << c[i];
}

}

高精度乘法

思路

  • 将两个字符串逆序存入整数数组
  • 循环数组 a 每一位,用 a[i] 乘以 b[j]
  • 结果错位加到 c [i+j] 这一位上 逆序输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include<iostream>
using namespace std;

int main(){
string s1,s2;
int a[250]={0},b[250]={0},c[500]={0};

// 将高精度整数存入字符串
cin >> s1 >> s2;

// 将两个高精度整数逆序存入ab两个整数数组
for(int i=0;i<s1.size();i++){
a[s1.size()-i-1] = s1[i] - '0';
}
for(int i=0;i<s2.size();i++){
b[s2.size()-i-1] = s2[i] - '0';
}

// 逐位相乘,错位相加
for(int i=0;i<s1.size();i++){
for(int j=0;j<s2.size();j++){
c[i+j] = a[i] * b[j] + c[i+j];
// 进位
if(c[i+j]>=10){
c[i+j+1] += c[i+j]/10;
c[i+j] %= 10;
}
}
}

// 逆序从第一个非0的数字开始输出
int p=-1; //记录第一个非0数下标
for(int i=s1.size() + s2.size() - 1;i >= 0 ; i--){
if(c[i]!=0){
p = i;
break;
}
}
if (p==-1) {
cout << 0;
return 0;
}
for(int i=p;i>=0;i--){
cout << c[i];
}
}

高精度除法

思路

  • 模拟除法运算过程,不断重复借位除以小数位,用n限制小数位
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
using namespace std;

int main(){
int a,b,n,t;
cin>>a>>b>>n;

// 输出整数部分
cout<< a/b << ".";
// 模拟除法运算,补零计算n次小数位
t = a % b;
for(int i=0;i<n;i++){
t *= 10;
cout<<t/b;
t %= b;
}
}