这个乘法的思路和我们习惯的笔算乘法是反过来的:是用高精度的一位乘以低精度,然后确认本位和进位:
A = 123, b = 12; // 实际中A可能会远大于b
A * b =
1 2 3
× 1 2
------------------
c4 c2 c1 c0
c0 = (3 × 12 + 0 ) % 10 = 6; t1 = (3×12)/10 = 3;
c1 = (2 × 12 + t1) % 10 = 7; t2 = 2;
c2 = (1 × 12 + t2) % 10 = 4; t3 = 1;
c4 = 1;
对于上面这个乘法,我们是这么算的:3*12 + 20*12 + 100*12
。和我们习惯的笔算乘法是反过来的,但当然是对的。因为在存c4~c0
的时候,存的位置的先后顺序本身就暗含了10^k
的权重,所以我们要关心的就是3*12
, 2*12
, 1*12
和每次的进位。也就是上面的过程。
把上面的过程翻译成代码如下:
// C = A * B, A >= 0, B >= 0
vector<int> mul(vector<int> &A, int b)
{
vector<int> C;
int t = 0;
for (int i = 0; i < A.size() || t; i ++){
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back(); // 删除前缀0
return C;
}
思路就是我们笔算的除法步骤:
A = 12345;
b = 33;
c = 0 0 3 7 4
--------------
33 |1 2 3 4 5
- 9 9
--------------
2 4 4
- 2 3 1
-------------
1 3 5
- 1 3 2
--------------
r = 3
将上面的过程翻译成代码:
// A / b = 商C ... 余数r, A >= 0, b > 0
vector<int> div(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); // int 除法的结果会抹掉小数位
r %= b; // 留在本位的参与下一次减法
}
reverse(C.begin(), C.end()); // 低位存在前
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
考虑通常加减乘除都会出现,所以这里的A
还是把低位存在前面。由于除法要从高位开始做,所以看到循环是从A.size( ) - 1
开始的。调用格式为:
vector<int> A = {5,5,5,5,5,5};
int b = 56;
int r = 0;
auto C = div(A, b, r);
for (int i = C.size() - 1; i >= 0; i --) printf("%d",C[i]);
cout << endl << r << endl;
因篇幅问题不能全部显示,请点此查看更多更全内容