Series: Multiple-Precision Arithmetic

Addition

Published on , updated on

This post will cover a basic addition algorithm for multiple-precision non-negative integers. The algorithm is based upon that presented in Section 4.3.1, The Classical Algorithms, of The Art of Computer Programming, Volume 2, by Donald E. Knuth. The notation and bounds used in this post were presented in a previous post.

We consider adding two nn-digit numbers with n≥1n \geq 1, u=(un−1…u1u0)bu=(u_{n-1} \ldots u_1 u_0)_b and v=(vn−1…v1v0)bv=(v_{n-1} \ldots v_1 v_0)_b. Since bn−1≤u,v≤bn−1b^{n-1} \leq u, v \leq b^n - 1 we have 2bn−1≤u+v≤2bn−22 b^{n-1} \leq u+v \leq 2 b^n - 2 which, when using the fact that b≥2b \geq 2, leads to bn−1≤u+v≤bn+1−1b^{n-1} \leq u+v \leq b^{n+1} - 1 (note how a tighter bound of the form bp≤u+v≤bq−1b^p \leq u+v \leq b^q - 1 is not possible).

This means that u+vu+v can be represented using nn or n+1n+1 digits, so we set w=(wn…w1w0)bw=(w_n \ldots w_1 w_0)_b.

Assuming k0k_0 is set to some initial value (more on this below) we now have the following algorithm:

wi←(ui+vi+ki)  mod  bki+1←⌊(ui+vi+ki)/b⌋\begin{aligned} w_i &\leftarrow (u_i + v_i + k_i) \;\text{mod}\; b \\ k_{i+1} &\leftarrow \lfloor (u_i + v_i + k_i)/b \rfloor \end{aligned}

for i=0,1,…,n−1i = 0, 1, \ldots, n-1, and finally wn←knw_n \leftarrow k_n.

The algorithm sets the digits of ww such that w=u+v+k0w = u+v+k_0. This can be seen by first observing that p=p  mod  b+⌊p/b⌋bp = p \;\text{mod}\; b + \lfloor p/b \rfloor b for any integer pp. Using this relation on the variables set during the algorithm, we have

ui+vi+ki=wi+ki+1bu_i + v_i + k_i = w_i + k_{i+1} b

for i=0,1,…,n−1i = 0, 1, \ldots, n-1. We now have

u+v=∑i=0n−1(ui+vi)bi=∑i=0n−1(ui+vi+ki)bi−∑i=0n−1kibi=∑i=0n−1(wi+ki+1b)bi−∑i=0n−1kibi=∑i=0n−1wibi+knbn−k0,\begin{aligned} u+v &= \sum_{i=0}^{n-1} (u_i+v_i) b^i = \sum_{i=0}^{n-1} (u_i+v_i+k_i) b^i - \sum_{i=0}^{n-1} k_i b^i \\ &= \sum_{i=0}^{n-1} (w_i+k_{i+1} b) b^i - \sum_{i=0}^{n-1} k_i b^i = \sum_{i=0}^{n-1} w_i b^i + k_n b^n - k_0, \end{aligned}

showing that w=u+v+k0w=u+v+k_0.

It is clear that each resulting digits of ww satisfies 0≤wi≤b−10 \leq w_i \leq b-1 for i=0,…,n−1i = 0, \ldots, n-1, as it should. The value of wnw_n, though, depends on knk_n.

Assume that 0≤ki≤10 \leq k_i \leq 1 for some i=0,…,n−1i=0, \ldots, n-1. Since ui+vi+ki≤b−1+b−1+1=2b−1u_i+v_i+k_i \leq b-1+b-1+1 = 2b-1 we see that ki+1=⌊(ui+vi+ki)/b⌋≤1k_{i+1} = \lfloor (u_i + v_i + k_i)/b \rfloor \leq 1. So if we have 0≤k0≤10 \leq k_0 \leq 1 as initial value for the algorithm we have, by induction, that 0≤ki≤10 \leq k_i \leq 1 for all i=0,…,ni=0, \ldots, n.

This shows how (not surprisingly) k0k_0 can be seen as an “initial carry” and how each ki+1k_{i+1} is 00 or 11, depending on whether a carry was produced from the $i$th digit addition.

Next, multiple-precision number subtraction.