This page actually discusses implementing division algorithms for digital circuits (i.e. a divider in a microprocessor math unit). Many other types of division
| This is an archive of past discussions about Division algorithm. Do not edit the contents of this page. If you wish to start a new discussion or revive an old one, please do so on the current talk page. |
| Archive 1 |
This page actually discusses implementing division algorithms for digital circuits (i.e. a divider in a microprocessor math unit). Many other types of division also exist for electronics that are not addressed in this page (e.g. voltage divider, current divider, etc)
~~~~
The algorithm as described is inefficient. If the only two digits used are 1 and -1, the latter can be represented as 0, then:
Q = P (positive term) N (the negative term) = ~P = -P-1 Two's complement of N (-N) = P+1
The sum of P and -N = 2*P + 1.
Therefore, the least significant digit for the quotient is always 1, and the overall precision is one less bit than expected.
A better implementation of non-restoring division is to allow digits 0, 1, and -1 (this will require twice the number of state devices for the quotient, though):
P[0] = N
i = 0
while(i<n)
{
if(abs(P[i]) < 0.25) q[n-(i+1)] = 0;
else if(P[i] >= 0) { q[n-(i+1)] = 1; P[i+1] = 2*P[i] - D; }
else { q[n-(i+1)] = -1; P[i+1] = 2*P[i] + D; }
i++;
}
Comparing with 0.25 is cheap: the absolute value is less than 0.25 if the two most significant bits of mantissa are equal to the sign bit.
((That's essentially SRT now, isn't it? -Ben))
I'm not smart enough to understand any of the formulas on this article and I don't know which this is, but I do know that this is not the best routine - but it is a simple example of integer division in compilable C code. I only post it to talk page because I came here looking for such a thing and couldn't find it, so when I figured it out, I post it here. Just delete it if you don't like. I won't be offended. Maybe one person will be helped.
int Q=0;
int N=100000000; //1.00000000
int D=3183; //0.3182 (in other words, 1/PI) - the result should be pi.
int mult=65536;
while(mult>0)
{
if((N-(D*mult))>=0)
{
N=N-(D*mult);
Q=Q+mult;
}
mult=mult>>1; //Right-shift by 1 bit..
}
printf ("Q=%d, R=%d\n",Q,N);
Anyway, after the loop is done, N contains the remainder. This code is very limited and for illustration only. PS: C code and this page don't get along.
64.146.180.232 (talk) 03:53, 11 July 2008 (UTC)
Hi, I just fixed some issues in the pseudocode. As all pseudocode it is untestable, and thus likely to be buggy. Below you find a C implementation of same complexity for the restoring unsigned integer division, but compile- and verifiable:
/** save as d u_div.c -- compile & test by typing:
* gcc -Wall -g -O0 -o u_div u_div.c && ./u_div 100 10
*/
#include <stdio.h>
#include <stdlib.h>
long long i_div (long long bit_width, long long P, long long D)
{
long long P_sub_D;
long long q = 0;
long long i;
D <<= bit_width;
for (i=bit_width-1; i>=0; i--) {
P = 2 * P;
P_sub_D = P - D;
if (P_sub_D >= 0) {
P = P_sub_D;
q |= (1 << i);
}
}
return q;
}
int main (int argc, char **argv)
{
long long P = strtoll(argv[1], NULL, 0);
long long D = strtoll(argv[2], NULL, 0);
long long bit_width = 16; // word width
printf("%lld / %lld = %lld\n", P, D, i_div(bit_width, P, D));
return 0;
}
Hope this helps to make the situation better, -- 89.247.39.228 (talk) 18:36, 29 July 2008 (UTC)
It's essentially the same thing as Newton's itterations, just written in a different form.
IMHO if anything else should be mentioned regarding fast division are those two things:
1. How to derive iteration formula with cubic convergence order (or write the formula itself).
Higher order convergence is of no real use here.
2. Numerical error and achievable accuracy.
It's very important, because for instance when N=32, for most numbers achievable accuracy
is lower by one digit of importance than what can be represented on the machine.
79.178.123.70 (talk) 15:15, 28 June 2009 (UTC)
I have seen the algorithm etc. When becomes small enough, then the denominator is set to 1 and the algorithm terminates. Does someone know its name or better a reference? I believe it was used in an IBM machine. HenningThielemann (talk) 16:45, 25 March 2010 (UTC)
As presented, the algorithm has two errors:
The two issues are:
I would present the algorithm so it looks similar to the restoring version. Here is a suggested replacment for the entire section:
Suggested replacement for the entire section:
Non-restoring division uses the digit set {−1,1} for the quotient digits instead of {0,1}. The basic algorithm for binary (radix 2) non-restoring division is:
P := N
D := D << n * P and D need twice the word width of N and Q
for i = n-1..0 do * for example 31..0 for 32 bits
if P >= 0 then
q[i] := 1
P := 2*P - D
else
q[i] := -1
P := 2*P + D
end if
end
* Note: N=Numerator, D=Denominator, n=#bits, P=Partial remainder, q(i)=bit #i of quotient.
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:
| Convert the following quotient to the digit set {0,1}: | |
| Steps: | |
| 1. Form the positive term: | |
| 2. Mask the negative term: | |
| 3. Subtract: minus : |
If the -1 digits of are stored as zeros (0) as is common, then is and computing is trivial: perform a bit-complement on the original .
Q := Q - (Q ^ (-1)) * Appropriate if -1 Digits in Q are Represented as zeros as is common.
Finally, quotients computed by this algorithm are always odd: 5 / 2 = 3 R -1. To correct this add the following after Q is converted from non-standard form to standard form:
if P < 0 then
Q := Q - 1
P := P + D * Needed only if the Remainder is of interest.
end if
The actual remainder is P >> n.
Michael Mulligan (talk) 15:24, 21 June 2010 (UTC)
In subsection Division (digital)#Newton–Raphson division, it gave a formula for X0 (the initial approximation to 1/D) as a linear function of D (the divisor) which it claimed would minimize the maximum of the absolute error of this approximation on the interval [0.5, 1]. Using Fermat's theorem (stationary points)#Application to optimization, I determined that the coefficients given were incorrect; and I replaced them with the correct coefficients. However, I subsequently realized that the formula which I gave required one multiplication while the previous formula required no multiplications (since its coefficient for D was −2 and −2D = −D−D). Even if one forces the coefficient for D to be −2, the other coefficient originally given would still have been wrong. However, avoiding the cost of the multiplication by −32/17 in my version might be the right choice in some implementations, so I want to show what happens if we use −2 for the coefficient of D.
Suppose we want to choose T to minimize the maximum absolute error when calculating Then So and thus the critical points lie at If we assume that the absolute error is maximized at and has opposite signs, then we get Thus and
To verify that this is correct, let us calculate at each of the three critical points:
if then
if then
if then
So the extreme points are as we assumed and the coefficient T that we calculated is correct. Let me repeat that the extremal error is worse for this formula than for the one given in the current version of the article, but it saves one multiplication. JRSpriggs (talk) 08:44, 13 November 2010 (UTC)
Looking at table 1 of your reference gave me a brain-storm: I can eliminate the one multiplication without sacrificing precision if I just move the interval within which D lies. If instead of shifting D into [1/2, 1], I shift it into then which requires no multiplication but still gives JRSpriggs (talk) 08:24, 14 November 2010 (UTC)
I didn't find best approximation in terms of relative error, but I found to minimize the maximum absolute error for on the interval . The error is then --MrOklein (talk) 20:43, 19 January 2013 (UTC)
I think the best approximation in terms of relative error is for the same function on the same interval. The maximal relative error here is . --MrOklein (talk) 21:12, 19 January 2013 (UTC)
The distinctive difference between Non Restoring and SRT division is incorrectly described as the use of a table. Radix 2 division uses digits +1, 0 and -1, don't need any table and deliver one result bit per iteration. Higher radix SRT division (for example Radix 4, digits +2,+1,0,-1 and -2) need a table as digit selection depends on the divisor and remainder (not dividend, except for the first iteration) values.
The main advantage of SRT division for electronic circuit design is that an approximate value of the remainder is used for digit selection at each iteration, instead of the exact value. Faster, non carry propagating adders can be used. That in turn enables higher precision, shorter cycle time or the calculation of several bits par cycle either by using a high radix divider or by combining several Radix 2 cells — Preceding unsigned comment added by 194.98.70.14 (talk) 11:13, 16 June 2011 (UTC)
This new section stuck at the beginning is basically the same algorithm as the restoring division one. However neither of them is cited and I think the actual code in the restoring division one is a bit clunky. So I think I'll add citation needed to both and then we can keep the one that is cited first and remove the other one. Dmcq (talk) 23:04, 20 February 2012 (UTC)
I really think this section should be removed. It's just a bad implementation of the restoring division algorithm. --108.49.86.122 (talk) 16:35, 24 December 2019 (UTC)
I recently moved Division (digital) to Division algorithm, replacing a former redirect to Euclidean division. In retrospect this was too bold - I belatedly discovered that the term "division algorithm" is used (idiosyncratically) to refer to the theorem outlined at Euclidean division as well as to algorithms that perform division. I've fixed all the links now, and I think it makes sense for the primary topic to refer to the more obvious subject. I think it also makes sense to have a general article about division algorithms, similar to multiplication algorithm, rather than one solely concerned with division algorithms used in digital circuits. Unlike Adder (electronics), dividers are too complex to describe in detail at the logic or gate level, so most of what's here is already pseudocode suitable for implementation in a variety of hardware, software, and other settings. As such few changes were needed except to add some info on basic slow algorithms not normally used in implementations, which I think help in any case to introduce the notation and serve as a behavioural reference for the more complex ones. Feedback is welcome. Dcoetzee 12:31, 23 September 2012 (UTC)

The article claims:
It seems that the error is actually bounded by 2/17, not 1/17. Measuring error at the two endpoints and the single local maximum, we find error is 1/17 at D=1, 2/17 at D=1/2, and or about 1.36/17 at the local maximum. This would imply the estimate for S may be incorrect (should have rather than ).
I also attempted a derivation of the optimal linear approximation in terms of max error. The max error for f(x)=a-bx is given by , assuming it crosses 1/x twice in [0.5, 1]. The planes 2-a+b/2 and 1-a+b have a difference of 1-b/2, so they intersect where b = 2; where b < 2, the plane 2 - a + b/2 is higher, and where b > 2, the plane 1-a+b is higher.
When b < 2 the functions and intersect where , along which max error is , which is minimized at endpoint b=2, giving the approximation which has max error of or about 0.0857864.
When b > 2 the functions and intersect where , along which max error is , which is again minimized at endpoint b=2, giving the same result as before.
In short the optimal linear approximation appears to be with a max error of or about 0.0857864 < 1/11, as compared to 2/17 or 0.117647 < 1/8 for the one given in the article. Not only is the approximation better, but it saves a multiply since 2D is just a shift. Obviously I can't add this to the article since it's original research, but it does suggest that the approximation we're suggesting is suboptimal. Even rational approximations of this solution are better than the suggested one (e.g. 50/17 - 2D gives a max error of 0.112749, 32/11 - 2D gives 0.0909091, and 102/35 - 2D gives 0.0858586).
Note that the average error squared given by the integral is not quite as good as for the currently supplied function which gives 0.00155871, so there is that tradeoff. However if there is no test for convergence and the number of iterations is determined solely by the desired precision, then average error doesn't help. Dcoetzee 05:26, 24 September 2012 (UTC)
I have tagged this section {{expand-section}} not only because it is a stub, but mainly because some important material is completely lacking in the article, mainly the problem of correct rounding. The section should mention the norm IEEE 754 and describe how the algorithms have to be modified (and have been) to follow this norm. Also, and this is related, this section should mention Intel bug. D.Lazard (talk) 09:52, 24 September 2012 (UTC)
This algorithm for signed integers produces quotient bits of 0 and 1. The dividend has double the number of bits as the divisor, quotient, and remainder. In this example, a 32 bit dividend is divided by a 16 bit divisor, producing a 16 bit quotient and remainder. There are some pre and post processing steps used to handle negative divisors, and clean up of the remainder. The overflow logic is not included.
#include <stdio.h>
/* signed integer non restoring divide, no overflow check */
/* quotients round down towards negative infinity */
/* shorts are assumed to be 16 bits, ints are assumed to be 32 bits */
/* unsigned variables are used to prevent sign extension by C */
unsigned int divide(unsigned int dvnd, unsigned short dvsr)
{
int i;
unsigned short qb; /* quotient bit */
unsigned short q; /* quotient */
if(dvsr>>15) /* if dvsr negative, decrement dvnd */
dvnd -= 1;
q = 0;
qb = (dvnd>>31) == (dvsr>>15); /* if signs same, qb = 1, else qb = 0 */
/* and if signs same, subtract, else add */
i = 0;
while(1){
dvnd = qb ? dvnd - ((unsigned int)dvsr<<16) : dvnd + ((unsigned int)dvsr<<16);
qb = (dvnd>>31) == (dvsr>>15);
q = (q<<1) | qb;
if(++i == 17)
break;
dvnd <<= 1;
}
if((dvnd>>31) != (dvsr>>15)) /* if remainder wrong sign, add dvsr */
dvnd += (unsigned int)dvsr<<16;
if(dvsr>>15) /* if dvsr negative, increment remainder */
dvnd += 0x10000;
return(dvnd | q);
}
int main(){
char buffer[80];
unsigned int m0, m1;
while(1){
printf("enter numbers in hex: ");
fgets(buffer, sizeof(buffer), stdin);
if(2 != sscanf(buffer, "%x %x", &m0, &m1))
break;
m0 = divide(m0, (unsigned short)m1);
printf("quotient is: %4x remainder is %4x\n", m0 & 0xffff, m0>>16);
}
return 0;
}
Rcgldr (talk) 16:39, 22 November 2013 (UTC)
Labelling some algorithms as "slow" and others as "fast" can be a bit misleading, particularly from the perspective of hardware implementation.
There are additive methods (non restoring, SRT) and multiplicative ones (newton, goldshmidt...).
The multiplicative methods converge in fewer steps, but these steps are far more complex, because a multiplication is more complex than an addition. The multiplicative methods also require an initial approximation wich incurs some delay and area.
The Goldshmidt method purpose' is also related to multiplication speed. It has some issues with precision and accumulating errors, but it has the benefit of using two independant multiplications per iteration, instead of dependant ones for Newton. It enables to use two parallel multipliers or one pipelined two-cycles multiplier. — Preceding unsigned comment added by Temlib (talk • contribs) 23:06, 24 July 2014 (UTC)
I saw this improved algorithm but it isn't peer reviewed
"Labor of Division (Episode III): Faster Unsigned Division by Constants" (PDF). ridiculous_fish. October 19, 2011.
I'm pretty certain it is okay butdon't feelitpasses reliable sources, or does it if ridiculous fish has released an open source library with improved division algorithms and might be known as n authority? Dmcq (talk) 23:46, 25 September 2014 (UTC)
I generated X86 assembly code for 16, 32, and 64 bits to confirm the algorithm. In the article, a uword has N bits, a udword has 2N bits, n = numerator, d = denominator = divisor, ℓ is initially set to ceil(log2(d)), shpre is pre-shift (used before multiply) = e = number of trailing zero bits in d, shpost is post-shift (used after multiply), prec is precision = N - e = N - shpre. The goal is to optimize calculation of n/d using a pre-shift, multiply, and post-shift.
Scroll down to figure 6.2, which defines how a udword multiplier (max size is N+1 bits), is generated, but doesn't clearly explain the process. I'll explain this below.
Figure 4.2 and figure 6.2 show how the multiplier can be reduced to a N bit or less multiplier for most divisors. Equation 4.5 explains how the formula used to deal with N+1 bit multipliers in figure 4.1 and 4.2 was derived.
Going back to Figure 6.2. The numerator can be larger than a udword only when divisor > 2^(N-1) (when ℓ == N), in this case the optimized replacement for n/d is a compare (if n>=d, q = 1, else q = 0), so no multiplier is generated. The initial values of mlow and mhigh will be N+1 bits, and two udword/uword divides can be used to produce each N+1 bit value (mlow or mhigh). Using X86 in 64 bit mode as an example:
; upper 8 bytes of numerator = 2^(ℓ) = (upper part of 2^(N+ℓ))
; lower 8 bytes of numerator for mlow = 0
; lower 8 bytes of numerator for mhigh = 2^(N+ℓ-prec) = 2^(ℓ+shpre) = 2^(ℓ+e)
numerator dq 2 dup(?) ;16 byte numerator
divisor dq 1 dup(?) ; 8 byte divisor
; ...
mov rcx,divisor
mov rdx,0
mov rax,numerator+8 ;upper 8 bytes of numerator
div rcx ;after div, rax == 1
mov rax,numerator ;lower 8 bytes of numerator
div rcx
mov rdx,1 ;rdx:rax = N+1 bit value = 65 bit value
Rcgldr (talk) 05:49, 20 January 2017 (UTC)
In this text :
Express D as M × 2e where 1 ≤ M < 2 (standard floating point representation)
D' := D / 2e+1 // scale between 0.5 and 1, can be performed with bit shift / exponent subtraction
N' := N / 2e+1
X := 48/17 - 32/17 × D' // precompute constants with same precision as D
repeat times // can be precomputed based on fixed P
X := X + X × (1 - D' × X)
end
return N' × X
I'm just curious on how many iterations that are performed in that case? Since the algorithm does two MUL and two ADD each iteration, I assume that only five iterations are needed then? Correct? — Preceding unsigned comment added by Eleteria (talk • contribs) 09:35, 28 February 2016 (UTC)
should you not mention the recursive one, for non-negative integers ?
div(a,b) a < b => 0 else => 1 + div(a-b,b) — Preceding unsigned comment added by 87.240.239.70 (talk) 18:37, 23 June 2016 (UTC)
In this section it states "while making use of the second expression, one must compute the product between and with double the required precision (2n bits)." It appears to me that the required precision would be n+1 bits. Rcgldr (talk) 18:21, 28 December 2016 (UTC)
Let divide 123 by 45. Will have 123 / 4 to got quotient 30. Then divide 30 by 15. Will have 30 / 15 to got quotient 2. It is divide the number, answer is quotient 2. The only except divide by numbers 11, 111, 1111 ... If one try divide 22 by 11 he will got exact 2. Now let such calculate do the exact number to select. That sequence of digit 1 should to select on divisor value. See further a sample how to: 123 / 4 (the number 4 is !digit! of number 45). To the end, a digits of divisor should prepared append a digit 1. Then digit 5 should have 15. This easy can binary divide algorithm. I would accept any note on hardware implementation of "chipdie" divide.95.78.44.26 (talk) 08:46, 5 April 2017 (UTC) Victor Mineev
See Division algorithm#Newton–Raphson division. I noticed that one can reduce the number of iterations required if one makes the error converge faster after each iteration. Specifically, let
Then
If we assume that the calculator or computer which we are using does all its multiplications to the same precision and at the same cost, then we can minimize the over-all cost of the required iterations if we choose k such that precision gained per multiplication is maximized. That is, maximize
since each iteration requires k+1 multiplications and multiplies the precision by k+1. It is easily determined that this occurs when k+1 = 3, i.e. when k = 2. So the method that I am recommending is
OK? JRSpriggs (talk) 06:52, 19 May 2018 (UTC)
Another part of the algorithm which can be improved is the calculation of the initial estimate X0. If we allow two multiplications (instead of just one) in the formula for the initial estimate, then we can use
for D in the interval [0.5, 1.0]. This gives a maximum absolute value of the error of
which is considerably better than the 1/17 which we currently are using. In fact,
So this is a better use of one extra multiplication than either half a Newton-Raphson iteration or a third of an iteration of the method which I explained in my previous comment here. Finding the coefficients which would give such a good result took considerable effort. So probably any further improvement in the initial estimate should rely on a table look-up. JRSpriggs (talk) 07:18, 22 May 2018 (UTC)
If three multiplications are used in getting the initial estimate, then I determined that the best cubic polynomial approximation to 1/D in [0.5, 1.0] would have a maximum absolute value of the error of 1/577. While this looks better than 1/99, it is not enough of an improvement to justify using the additional multiplication for that rather than to do more Newton-Raphson iterations. I used a figure of merit of
where M is the maximum absolute value of the error in the estimate. This measures the number of Newton-Raphson iterations avoided relative to just using an initial estimate of 1. I guess that this is an instance of the law of diminishing returns. JRSpriggs (talk) 14:44, 23 May 2018 (UTC)
I just became aware of Chebyshev polynomials of the first kind and realized that they provide the answer to getting the best initial estimate of 1/D for polynomials of a specified degree. If the degree is to be n, then
and thus
where
Well, this just shows that there is nothing new under the Sun, and my ignorance vastly exceeds my knowledge. JRSpriggs (talk) 07:33, 24 May 2018 (UTC)
| name | 1/M | merit | delta |
|---|---|---|---|
| reference | 2 | 0 | n/a |
| best constant | 3 | 0.664 | n/a |
| best linear | 17 | 2.031 | 1.367 |
| best quadratic | 99 | 2.729 | 0.698 |
| best cubic | 577 | 3.197 | 0.468 |
| best quartic | 3363 | 3.550 | 0.353 |
| Newton-Raphson | square | +1.000 | 0.500 |
| variant N-R | cube | +1.585 | 0.528 |
The delta column shows the improvement in the merit per multiplication. The best linear approximation is way better than either the reference (X0 = 1) or the best constant (X0 = 4/3). The best quadratic is enough better than the best linear to justify using another multiplication. Neither best cubic nor best quartic improves enough to justify the extra multiplications. JRSpriggs (talk) 04:58, 25 May 2018 (UTC)
The same improvements which we made to Newton-Raphson division can be made to Goldschmidt division.
OK? JRSpriggs (talk) 08:14, 29 May 2018 (UTC)
It is possible to perform division by repeated subtraction of complementary numbers, but the magic is that the result is gradually built from modifying the divdend (by addition) and accumulating digits (that form the result of the division) to the left of what remains of the dividend; successive digits of the division appear from left to right as one proceeds through the algorithm. How this can work is not intuitive and could benefit from a theoretical explanation. (This method was used on adding machines) Axd (talk) 19:19, 31 July 2018 (UTC)
To be encyclopedic, some introduction and links to floating point, Continued fraction, Arbitrary-precision arithmetic, etc.
It would be nice if the article contained a concise comparison of the division methods: are some methods "better" than some others, in some respect? Currently there is very little that would help see how better and better division methods were developed, and what is the state of the art currently. At its present state the article is just a long list of different division algorithms. — Preceding unsigned comment added by 87.92.32.62 (talk) 11:32, 28 April 2019 (UTC)
The article must include details of galley division. —Jencie Nasino (talk) 02:20, 16 August 2019 (UTC)
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.