Division algorithm


A division algorithm is an algorithm which, given two integers N and D, computes their quotient and/or remainder, the result of Euclidean division. Some are applied by hand, while others are employed by digital circuit designs and software.
Division algorithms fall into two main categories: slow division and fast division. Slow division algorithms produce one digit of the final quotient per iteration. Examples of slow division include [|restoring], non-performing restoring, [|non-restoring], and [|SRT] division. Fast division methods start with a close approximation to the final quotient and produce twice as many digits of the final quotient on each iteration. [|Newton–Raphson] and [|Goldschmidt] algorithms fall into this category.
Variants of these algorithms allow using fast multiplication algorithms. It results that, for large integers, the computer time needed for a division is the same, up to a constant factor, as the time needed for a multiplication, whichever multiplication algorithm is used.
Discussion will refer to the form, where
is the input, and
  • Q = quotient
  • R = remainder
is the output.

Division by repeated subtraction

The simplest division algorithm, historically incorporated into a greatest common divisor algorithm presented in Euclid's Elements, Book VII, Proposition 1, finds the remainder given two positive integers using only subtractions and comparisons:
function divide_unsigned
if D = 0 then error end
R := N
Q := 0
while R ≥ D do
R := R − D
Q := Q + 1
end
return
end

The proof that the quotient and remainder exist and are unique gives rise to a complete division algorithm, applicable to both negative and positive numbers, using additions, subtractions, and comparisons:

function divide
if D = 0 then error end
if D < 0 then
:= divide
return
end
if N < 0 then
:= divide
if R = 0 then
return
else
-- Example: N = -7, D = 3
-- divide = divide =
-- R ≠ 0, so return =
-- Check: *3 + 2 = -7
return
end
end
-- At this point, N ≥ 0 and D > 0
return divide_unsigned
end

This procedure always produces R ≥ 0. Although very simple, it takes Ω steps, and so is exponentially slower than even slow division algorithms like long division. It is useful if Q is known to be small, and can serve as an executable specification.

Alternative implementation

An alternative implementation increments a remainder and resets it when it reaches the divisor.
For, the algorithm computes such that, with :
Consider this code in Python:

def divide_unsigned2 -> tuple
quotient: int = 0
remainder: int = 0
for _ in range:
remainder += 1
if remainder denominator:
quotient += 1
remainder = 0
return quotient, remainder

Notes
  • Special cases are
  • Variable quotient is never read. So when its assignments highlighted are removed from the code and quotient is removed from the output list, divide_unsigned2, like divide_unsigned, still will compute.
Alternative implementation as counter machine

A simple counter machine can be based on the alternative implementation. The CM instructions are
  • Z : Replace rn by 0.
  • S : Add 1 to rn.
  • J : If rm = rn, jump to the qth instruction; otherwise go on to the next instruction in the program.
The counter machine program is

1: J
2: S
3: J
4: S
5: J
6: S
7: Z
8: S
9: J

After the CM finishes the computation on initial register values R1=N, R2=D,

Long division

Long division is the standard algorithm used for pen-and-paper division of multi-digit numbers expressed in decimal notation. It shifts gradually from the left to the right end of the dividend, subtracting the largest possible multiple of the divisor at each stage; the multiples then become the digits of the quotient, and the final difference is then the remainder.
When used with a binary radix, this method forms the basis for the integer division with remainder algorithm below. Short division is an abbreviated form of long division suitable for one-digit divisors. Chunking also known as the partial quotients method or the hangman method is a less-efficient form of long division which may be easier to understand. By allowing one to subtract more multiples than what one currently has at each stage, a more freeform variant of long division can be developed as well.

Integer division (unsigned) with remainder

The following algorithm, the binary version of the famous long division, will divide N by D, placing the quotient in Q and the remainder in R. In the following pseudo-code, all values are treated as unsigned integers.
if D = 0 then error end
Q := 0 -- Initialize quotient and remainder to zero
R := 0
for i := n − 1.. 0 do -- Where n is number of bits in N
R := R << 1 -- Left-shift R by 1 bit
R := N -- Set the least-significant bit of R equal to bit i of the numerator
if R ≥ D then
R := R − D
Q := 1
end
end

Example

If we take N=11002 and D=1002
Step 1: Set R=0 and Q=0

Step 2: Take i=3

Step 3: R=00

Step 4: R=01 to N)

Step 5: R < D, so skip statement
Step 2: Set i=2

Step 3: R=010

Step 4: R=011

Step 5: R < D, statement skipped
Step 2: Set i=1

Step 3: R=0110

Step 4: R=0110

Step 5: R>=D, statement entered

Step 5b: R=10

Step 5c: Q=10
Step 2: Set i=0

Step 3: R=100

Step 4: R=100

Step 5: R>=D, statement entered

Step 5b: R=0

Step 5c: Q=11
end

Q=112 and R=0.

Slow division methods

Slow division methods are all based on a standard recurrence equation
where:
  • Rj is the j-th partial remainder of the division := N
  • B is the radix
  • q n is the digit of the quotient in position n−, where the digit positions are numbered from least-significant 0 to most significant n−1
  • n is number of digits in the quotient
  • D is the divisor

    Restoring division

Restoring division operates on fixed-point fractional numbers and depends on the assumption 0 < D < N.
The quotient digits q are formed from the digit set.
The basic algorithm for binary restoring division is:

R := N
D := D << n -- R and D need twice the word width of N and Q
for i := n − 1.. 0 do -- For example 31..0 for 32 bits
R := 2 * R − D -- Trial subtraction from shifted value
if R >= 0 then
q := 1 -- Result-bit 1
else
q := 0 -- Result-bit 0
R := R + D -- New partial remainder is shifted value
end
end
-- Where: N = numerator, D = denominator, n = #bits, R = partial remainder, q = bit #i of quotient

Non-performing restoring division is similar to restoring division except that the value of 2R is saved, so D does not need to be added back in for the case of R < 0.

Non-restoring division

Non-restoring division uses the digit set for the quotient digits instead of. The algorithm is more complex, but has the advantage when implemented in hardware that there is only one decision and addition/subtraction per quotient bit; there is no restoring step after the subtraction, which potentially cuts down the numbers of operations by up to half and lets it be executed faster. The basic algorithm for binary non-restoring division of non-negative numbers is:

-- Inputs: N, D
-- n = number of bits
-- R and D are usually stored in registers of width 2n or similar to handle shifts
R := N -- Initialize Remainder
for i = n − 1.. 0 do -- for example 31..0 for 32 bits
-- Shift Remainder Left
if R >= 0 then
R := 2 * R - D; -- Subtract D
q := 1; -- Record quotient bit as 1
else
R := 2 * R + D; -- Add D
q := -1; -- Record quotient bit as -1
end if
end for

Following this algorithm, the quotient is in a non-standard form consisting of digits of −1 and +1. This form needs to be converted to binary to form the final quotient. Example:
If the −1 digits of are stored as zeros as is common, then is and computing is trivial: perform a ones' complement on the original.

Q := Q − bit.bnot -- Appropriate if −1 digits in Q are represented as zeros as is common.

Finally, quotients computed by this algorithm are always odd, and the remainder in R is in the range −D ≤ R < D. For example, 5 / 2 = 3 R −1. To convert to a positive remainder, do a single restoring step after Q is converted from non-standard form to standard form:

if R < 0 then
Q := Q − 1
R := R + D -- Needed only if the remainder is of interest.
end if

The actual remainder is R >> n.

SRT division

SRT division is a popular method for division in many microprocessor implementations. The algorithm is named after D. W. Sweeney of IBM, James E. Robertson of University of Illinois, and K. D. Tocher of Imperial College London. They all developed the algorithm independently at approximately the same time.
SRT division is similar to non-restoring division, but it uses a lookup table based on the dividend and the divisor to determine each quotient digit.
The most significant difference is that a redundant representation is used for the quotient. For example, when implementing radix-4 SRT division, each quotient digit is chosen from five possibilities: −2, −1, 0, +1, or +2. Because of this, the choice of a quotient digit need not be perfect; later quotient digits can correct for slight errors. and This tolerance allows quotient digits to be selected using only a few most-significant bits of the dividend and divisor, rather than requiring a full-width subtraction. This simplification in turn allows a radix higher than 2 to be used.
Like non-restoring division, the final steps are a final full-width subtraction to resolve the last quotient bit, and conversion of the quotient to standard binary form.
The original Intel Pentium processor's infamous floating-point division bug was caused by an incorrectly coded lookup table. Pentium processors used a 2048-cell table, of which 1066 cells were to be populated, and values from five cells were mistakenly omitted.