高精度加减乘除
高精度
- 逆序存储数字
- 模拟的实现
- 考虑模拟细节(如零、前导零、负数、进位、借位、反转等)
高精度加法 O(n)
// C = A + B, 满足A >= 0, B >= 0
vector<int> add(vector<int> A, vector<int> B)
{
vector<int> C;
int t = 0; // 存储相加的结果和进位
// 模拟加法
for (int i = 0; i < A.size() || i < B.size(); i ++ )
{
if (i < A.size()) t += A[i];
if (i < B.size()) t += B[i];
C.push_back(t % 10);
t /= 10;
}
// 如果有进位
if (t) C.push_back(t);
return C;
}
高精度减法 O(n)
注意:考虑A<B结果为负数的情况
// C = A - B, 满足A >= B, A >= 0, B >= 0
vector<int> sub(vector<int> A, vector<int> B)
{
vector<int> C;
int t = 0; // 存储相减的结果和借位
for (int i = 0; i < A.size(); i ++ )
{
t += A[i] - (i < B.size()) * B[i];
C.push_back((t + 10) % 10);
t = (t < 0) * (-1);
}
// 去除前导零
while (C.size() > 1 && !C.back()) C.pop_back();
return C;
}
// 比较存储数字的A和B容器的大小
bool cmp(vector<int> A, vector<int> B)
{
// 如果长度不等
if (A.size() != B.size()) return A.size() > B.size();
// 如果值不等
for (int i = A.size() - 1; i >= 0; i -- )
if (A[i] != B[i]) return A[i] > B[i];
return true;
}
高精度乘低精度 O(n)
注意:考虑需要不停进位的情况
// C = A * b, A >= 0, b >= 0
vector<int> mul(vector<int> A, int b)
{
vector<int> C;
if (!A.back() || !b) return (C.push_back(0), C); // A不含前导零
int t = 0;
// 如果t作为乘数相加非常大, 需要不停进位
for (int i = 0; i < A.size() || t; i ++ )
{
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
// 如果含前导零的A,去除前导零
// while (C.size() > 1 && C.back() ` 0) C.pop_back();
return C;
}
高精度乘以高精度 O(n2)
注意:使用数组存储,注意每次循环的错位相加
// lena >= 0, lenb >= 0
void<int> multi(int a[], int b[], int c[], int lena, int lenb)
{
for (int i = 0; i < lena; i ++ )
for (int j = 0; j < lenb; j ++ )
{
c[j + i] += a[j] * b[i];
if (c[j + i] >= 10)
{
c[j + i + 1] += c[j + i] / 10;
c[j + i] %= 10;
}
}
// 去除前导零
int k = lena + lenb;
while (k >= 0 && !c[k]) -- k;
// 判断输出
if (k < 0) cout << 0;
while (k >= 0) cout << c[k -- ];
}
高精度除以低精度 O(n)
注意:兼容其他高精度算法,需从高位开始且翻转数组
// A / b = C ... r, A >= 0, b > 0
vector<int> div1(vector<int> A, int b, int &r)
{
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()) C.pop_back(); // 去除第一位是0的情况
return C;
}
低精度除法保留位数 O(n)
// a除以b保留前n为小数
void div2(int a, int b, int n)
{
if (!n)
{
cout << a / b;
return;
}
string res;
res.append(to_string(a / b) + '.');
int t = (a % b) * 10;
int k = 0; // 小数点位数
while (k < n - 1)
{
res.append(to_string(t * 10 / b));
t = (t * 10) % b;
k ++ ;
}
cout << res;
}

浙公网安备 33010602011771号