Multiplication algorithm: Difference between revisions

Content deleted Content added
added 'attention' False statement about fastest known method to multiply long integers (it's faster than O(nlognlog(logn)).Bad strcture (warmup example after main discussion)
right; this may not fix the problems, but at least it adds some structure
Line 2:
 
A '''multiplication algorithm''' is an [[algorithm]] (or method) to [[multiplication|multiply]] two numbers. Depending on the size of the numbers, different algorithms are in use.
 
== Long multiplication ==
 
A major advantage of [[numeral system|positional numeral system]]s over other systems of writing down numbers is that they facilitate the usual grade-school method of '''long multiplication''': multiply the first number with every digit of the second number and then add up all the properly shifted results. In order to perform this algorithm, one needs to know the products of all possible digits, which is why [[multiplication table]]s have to be memorized. Humans use this algorithm in base 10, while computers employ the same algorithm in base 2. The algorithm is a lot simpler in base 2, since the multiplication table has only 4 entries. Rather than first computing the products, and then adding them all together in a second phase, computers add the products to the result as soon as they are computed. Modern chips implement this algorithm for 32-[[bit]] or 64-[[bit]] numbers in [[hardware]] or in [[microcode]]. To multiply two numbers with ''n'' digits using this method, one needs about ''n''<sup>2</sup> operations. More formally: the time complexity of multiplying two ''n''-digit numbers using long multiplication is [[Big O notation|&Omicron;]](''n''<sup>2</sup>).
 
== Shifts and adds ==
 
An old method for multiplication, that does not require multiplication tables, is the [[Peasant multiplication]] algorithm; this is actually a method of multiplication using base 2.
 
A similar technique is still in use in computers where a binary number is multiplied by a small integer constant. Since multiplication of a binary number by powers of two can expressed in terms of bit-shifts, a series of bit shifts and addition operations which has the effect of performing a multiplication without the use of any conditional logic or hardware multiplier. For many processors, this is often the fastest way to perform these simple multiplications.
 
== Multiplication algorithms for computer algebra ==
 
===Karatsuba multiplication===
 
For systems that need to multiply huge numbers in the range of several thousand digits, such as [[computer algebra system]]s and [[bignum]] libraries, this algorithm is too slow.
Line 25 ⟶ 35:
 
It is possible to experimentally verify whether a given system uses Karatsuba's method or long multiplication: take your favorite two 100,000 digit numbers, multiply them and measure the time it takes. Then take your favorite two 200,000 digit numbers and measure the time it takes to multiply those. If Karatsuba's method is being used, the second time will be about three times as long as the first; if long multiplication is being used, it will be about four times as long.
 
===Toom-Cook===
 
Another Method of multiplication is called Toom-Cook or [[Toom3]]. The Toom-Cook method splits each number to be multiplied into multiple parts. Karatsuba is a special case of Toom-Cook using two parts. A three-way Toom-Cook can do a size-N<sup>3</sup> multiplication for the cost of five size-N multiplications, improvement by a factor of 9/5 compared to the Karatsuba method's improvement by a factor of 4/3. Using more parts eventually comes up against the law of diminishing returns.
 
=== Schönhage-Strassen algorithm ===
There exist even faster algorithms, based on the '''[[fast Fourier transform]]'''. The idea, due to [[Volker Strassen|Strassen]] (1968), is the following: multiplying two numbers represented as digit strings is virtually the same as computing the [[convolution]] of those two digit strings. Instead of computing a convolution, one can instead first compute the [[discrete Fourier transform]]s, multiply them entry by entry, and then compute the inverse Fourier transform of the result. (See [[convolution theorem]].) The fastest known method based on this idea was described in 1971 by [[Arnold Sch&ouml;nhage|Schönhage]] and [[Strassen]] ([[Schönhage-Strassen algorithm]]) and has a time complexity of &Theta;(''n'' ln(''n'') ln(ln(''n''))). The [[GIMPS]] distributed Internet [[prime number|prime]] search project deals with numbers having several million digits and employs a Fourier transform based multiplication algorithm. Using [[number-theoretic transform]]s instead of discrete Fourier transforms should avoid any [[rounding error]] problems by using [[modular arithmetic]] instead of [[complex number]]s.
 
All the above multiplication algorithms can also be used to multiply [[polynomial]]s.
 
There exist even faster algorithms, based on the '''[[fast Fourier transform]]'''. The idea, due to [[Volker Strassen|Strassen]] (1968), is the following: multiplying two numbers represented as digit strings is virtually the same as computing the [[convolution]] of those two digit strings. Instead of computing a convolution, one can instead first compute the [[discrete Fourier transform]]s, multiply them entry by entry, and then compute the inverse Fourier transform of the result. (See [[convolution theorem]].) The fastest known method based on this idea was described in 1971 by [[Arnold Sch&ouml;nhage|Schönhage]] and [[Strassen]] ([[Schönhage-Strassen algorithm]]) and has a time complexity of &Theta;(''n'' ln(''n'') ln(ln(''n''))). The [[GIMPS]] distributed Internet [[prime number|prime]] search project deals with numbers having several million digits and employs a Fourier transform based multiplication algorithm. Using [[number-theoretic transform]]s instead of discrete Fourier transforms should avoid any [[rounding error]] problems by using [[modular arithmetic]] instead of [[complex number]]s.
A simple improvement to the basic recursive multiplication algorithm:
 
: x&middot;0 = 0
: x&middot;y = x + x(y-1)
 
where x is an arbitrary quantity, and y is a natural number, is to use:
 
: x&middot;0 = 0
: x&middot;y = 2x&middot;(y/2), if y is divisible by 2
: x&middot;y = x + 2x&middot;(y/2), if y is not divisible by 2 (using integer division)
 
== Polynomial multiplication ==
The major improvement in this algorithm arises because the number of operations required is O(log y) rather than O(y). For numbers which can be represented directly as computer words a further benefit is that multiplying by 2 is equivalent to an arithmetic shift left, while division by 2 is equivalent to an arithmetic shift right. Clearly the major benefits arise when y is very large in which case it will not be possible to represent it as a single computer word.
 
All the above multiplication algorithms can also be usedexpanded to multiply [[polynomial]]s.
This may not help so much for multiplication by [[real number|real]] or [[complex number|complex]] values, but is useful for multiplication of very large integers ("[[bignum]]s") which are supported in some programming languages such as [[ Haskell programming language|Haskell]],
[[Java programming language|Java]], [[Ruby programming language|Ruby]], and
[[Common Lisp]].
 
==See also:==
* [[Strassen algorithm]].
 
==External links==