乘法演算法是計算兩個數值相乘乘積的演算法。為了提高運算效率，不同大小的數字適用不同的乘法演算法。自十進位制數字系統誕生以來，就已開始發展乘法演算法。 網格法 （或盒式法）是一種用於給小學生進行乘法計算啟蒙的簡單乘法演算法。自 1990 年代後期以來，它一直是英格蘭和威爾士公立小學數學課程的標準部分 Gary Eason Back to school for parents BBC News 13 February 2000Rob Eastaway Why parents cant do maths today BBC News 10 September 2010。 將兩個乘數分解（劃分）為百位、十位或個位的部分，然後在相對簡單的乘法步驟中直接算出這些部分的乘積，再將其一一相加以算出最終結果。用這種方法計算 34 times 13，可以畫出如下網格： 300 40 90 12 442 30 4 10 300 40 3 90 12 最後再透過一次求和或逐行累加得到結果（見右），實質是計算了 300 40 90 12 340 102 442。 這種計算方法（儘管不一定顯式地用網格排列乘數）也稱為「部分乘積演算法」。它的本質是分別計算簡單的個位乘法，所有加法都留到最後的「加總」階段。 儘管隨著位數的增加，伴隨的中間過程越來越繁瑣，但網格方法原則上可以應用於任何大小的乘數。一般認為此方式是引入多位乘法概念時，有用的顯式方法，而在當今利用計算器或電子表格就能完成大多數計算的時代，它可能是某些學生唯一需要的乘法演算法。 長乘法 位值制數字系統在人類社會的壟斷性地位，使得長乘法成為最自然的乘法演算法，世界各地的學校都會教學生使用這種演算法完成日常的乘法計算。其內容是：將一個乘數乘以另一個乘數的每位數字，然後將所有數字按照適當的位置相加得出結果。這需要預先記住所有個位數字兩兩相乘後的結果，即華人世界常見的乘法表。長乘法又被稱為教科書乘法或標準乘法。 若在十進位制下，人工計算較大的數字加乘，長乘法是常見的演算法。電腦在二進位制下，也有類似的演算法「移位和相加」，不少現代的處理器已設計最佳化的乘法線路，以進行快速的乘法計算，但其代價是硬體會變的更加複雜。若是在紙上計算長乘法，會先將所有數字寫下，然後相加，若是使用珠算，會在計算完每一個乘積後，直接和已計算的和加總。 示例 此例用長乘法計算 23958233（被乘數）乘以 5830（乘數），結果是 139676498390（積）。 23958233 5830 00000000 23958233 0 71874699 23958233 30 191665864 23958233 800 119791165 23958233 5000 139676498390 139676498390 以下的虛擬碼描述上述乘法的步驟。此作法會持續的更新乘積，在乘完所有數字後，乘積即為結果。其中 運運算元用來表示將某變數原有的值加上其他的值，再存回該變數中（類似在 Java 及 C 語言中的用法），以讓程式緊湊。 multiply a 1p b 1q base index 1 對應數字的個位數 product 1pq 先預留乘積的空間 for b_i 1 to q 針對 b 的每一位數 carry 0 for a_i 1 to p 針對 a 的每一位數 product a_i b_i 1 carry a a_i b b_i carry product a_i b_i 1 base product a_i b_i 1 product a_i b_i 1 mod base product b_i p carry 最高位數是最後一次計算乘法的進位 return product 最佳化空間複雜度 假設在基數為 D，令 n 為兩個輸入數字位數長度的總和，若其結果需儲存在儲存器中，則其空間複雜度通常為 Theta n。然而在某些應用中，不需要把整個結果儲存在記憶體中，而可以在計算時將數字以字元流的方式輸出（例如輸出到系統終端或檔案中）。在這些情況下，長乘法的優勢在於可以將其輕鬆表示為對數空間演算法 也就是說，只需要一個工作空間與輸入中位數的對數成正比的演算法（Theta log n），這是乘數之積的雙重對數（log log N）。注意，乘數本身仍保留在記憶體中，並且在此分析中忽略其 Theta n 的空間。 只要知道之前乘積產生的進位，就可以由最低位起，一位一位的計算乘積的每一位數字，這是最佳化空間複雜度的關鍵。令 ai 和 bi 分別是被乘數及乘數的第 i 位數字，a 和 b 的最高位都已補 0，補到 n 位數，而 ri 是乘積的第 i 位，而 ci 是計算 ri 後產生的進位（i1 表示是個位），則 begin align r_i left c_i1 sum_jki1 a_j b_k right mod D c_i leftlfloor c_i1 sum_jki a_j b_k D rightrfloor c_0 0 end align or c_i left sum_m 0i 2 sum_j k i m a_j b_k right D 簡單的推論可以證明進位不會超過 n，ri 的總和不會超過 D n：第一欄的進位是 0，其他欄最多有 n 個數字，最多也只會從前一欄進位 n。總和最多是 D n，進位到下一位的最多是 D n D 或 n。因此這些數字都可以用 O log n 位數儲存。 偽程式碼下的對數空間演演算法為： multiply a 1p b 1q base Operands containing rightmost digits at index 1 tot 0 for ri 1 to p q 1 For each digit of result for bi MAX 1 ri p 1 to MIN ri q Digits from b that need to be considered ai ri bi 1 Digits from a follow symmetry tot tot a ai b bi product ri tot mod base tot floor tot base product pq tot mod base Last digit of the result comes from last carry return product 在計算機中的用法 有些積體電路會實現乘法，可能是用硬體或是微程式，可能針對各種整數及浮點數。在高精度計算中，在乘比較小的數字時，用底數為 2w 的長乘法，其中 w 為字元的位元數。 若要用此方式乘二個 n 位數數字，約需要 n2 次的運算。若用比較型式的方式表示，用數字位數這個自然的數字大小度量，用長乘法乘二個 n 位數數字的時間複雜度是 Θn2。 若要用軟體實現，長乘法演演算法需要處理在加法時會出現的溢位問題，可能會很耗成本。典型的作法是用比較小的基底來進行運算，例如 b，而讓 8b 為機器中表示的整數大小。這樣可以進行幾次運算之後才會溢位。若數字太大，可以只加數字的一部份到結果中，或是進位，將剩下的數字對映為一個小於 b 的較小數字。此作法稱為「正規化」。Richard Brent 有在其 Fortran 軟體包 MP 中使用此一作法。 格子乘法 格子乘法在演演算法上和長乘法等效。需要在紙上劃格子，以引導計算，並且將乘法和加法分為二個步驟進行。這是在 1202 年在斐波那契的《》中引進到歐洲。斐波那契用此方式心算，用左手和右手處理計算的中間值。16 世紀的在《Umdetul Hisab》書籍上列出了此演演算法六種不同的變體。在奧斯曼帝國的恩德倫學校中，廣為使用此一演演算法 Corlu M S Burlbaw L M Capraro R M Corlu M A Han S 2010 The Ottoman Palace School Enderun and The Man with Multiple Talents Matrakçı Nasuh Journal of the Korea Society of Mathematical Education Series D Research in Mathematical Education 14 1 pp 1931。納皮爾的骨頭（Napiers bones）或稱為納皮爾算籌（Napiers rods）也是用此方式，是約翰納皮爾過世的 1617 年發表。 如圖所示，被乘數和乘數寫在格子的上方和右邊，此方法在花拉子米的《算數》（Arithmetic）書中有提到，這是斐波那契的來源之一，曾被 Sigler 在 2002 年的《Fibonaccis Liber Abaci》中提到。 在乘法階段，格子中會填上其對應行和列上所寫，被乘數和乘數的位數相乘後的二位數乘積：格子中左上方的三角形會列十位數字，格子中右下方的三角形會列個位數字。 在加法階段，會延著斜線將數字相加，將相加後的個位數寫在格子的最下方，對應斜線，若有進位，將進位寫在下一個斜線區域格子的右方或上方。 下方的數字即為兩數字相乘的積。 示例 考慮以下較複雜的計算，考慮 23958233 乘以 5830，結果是 139676498390。不過以下計算中，其中的 23958233 是寫在格子的上方，5830 寫在右方。將乘積寫在格子的二個三角形中，將和寫在左邊和下方。結果條列如下： 2 3 9 5 8 2 3 3 1 4 2 4 1 1 1 5 01 0 5 5 5 0 0 5 5 2 7 4 6 1 2 2 8 02 6 4 2 0 4 6 4 4 0 2 1 2 0 0 0 3 17 6 9 7 5 4 6 9 9 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 0 26 15 13 18 17 13 09 00 01 002 0017 00024 000026 0000015 00000013 000000018 0000000017 00000000013 000000000009 0000000000000 139676498390 2 3 9 5 8 2 3 3 139676498390 二進位制或農夫演演算法 是廣為在農民中使用的演算法，其中不需要像長乘法一樣記憶乘法表。此演演算法曾在古埃及使用，農夫演演算法的優點是可以快速教授、不需要記憶、若沒有紙筆的話，也可以用其他東西輔助計算（例如籌碼），缺點是步驟比長除法要長，在計算大數字的乘法時不方便， 說明 在紙上，寫下被乘數，被乘數的下方寫下被乘數反覆除二（且無條件捨去小數）的結果，被乘數的旁邊寫下乘數，乘數下方寫上乘數反覆乘二的結果。一直到被乘數那一欄為 1 為止。將乘數那一欄的數字相加，但若被乘數那一欄為偶數，跳過此數字不累加，所得結果即為乘積。 示例 以下用農夫演演算法計算 11 乘以 3 。 十進位制：二進位制 11 3 1011 11 5 6 101 110 2 12 10 1100 1 24 1 11000 33 100001 說明上述的步驟： 二欄的最上方分別是 11 和 3。 11 除以 2（55）無條件捨去，變成 5，3 乘以 2（6）。 5 除以 2（25）無條件捨去，變成 2，6 乘以 2（12），這一行的最左邊（2）是偶數，因此 12 要劃掉，不能累加到乘積中。 2 除以 2（1），12 乘以 2（24） 將沒有劃掉的數字相加：3 6 24 33 此作法有效的原因是因為乘法滿足分配律，因此： begin align 3 times 11 3 times 1times 20 1times 21 0times 22 1times 23 3 times 1 2 8 3 6 24 33 end align 以下是一個複雜的例子，仍用之前用過的範例（23958233 and 5830）： Decimal Binary 5830 23958233 1011011000110 1011011011001001011011001 2915 47916466 101101100011 10110110110010010110110010 1457 95832932 10110110001 101101101100100101101100100 728 191665864 1011011000 1011011011001001011011001000 364 383331728 101101100 10110110110010010110110010000 182 766663456 10110110 101101101100100101101100100000 91 1533326912 1011011 1011011011001001011011001000000 45 3066653824 101101 10110110110010010110110010000000 22 6133307648 10110 101101101100100101101100100000000 11 12266615296 1011 1011011011001001011011001000000000 5 24533230592 101 10110110110010010110110010000000000 2 49066461184 10 101101101100100101101100100000000000 1 98132922368 1 1011011011001001011011001000000000000 1022143253354344244353353243222210110 （進位前） 139676498390 10000010000101010111100011100111010110 電腦中的二進位制乘法 這是農夫演演算法的變體。 二進位制下，長乘法會變成很簡單的處理，針對每一個被乘數位數的 1，將乘數往左位移適當的位元數，將乘數各次位移的結果相加，即為乘積。在一些中央處理器中，加法和位移的速度會比乘法要快，尤其被乘數不大，或是幾乎是定值的情形。 移位和相加 以往的電腦會用「移位和相加」的乘法來計算小整數的乘法。二進位制的長乘法和農夫演演算法都可以簡化到相同的演演算法。 在二進位制下，將數字和二進位制的一個位元相乘，可以簡化為各位元的邏輯與運算。會將算出來的部份和相加。，大部份目前的微處理器都會以此方式或是其他類似方式（例如布斯乘法演算法）實現不同整數以及浮點長度的乘法，，可能是用乘法器中或是微程式。 目前的處理器，位元的移位運算會比乘法要快很多，因此可以用往左移位代替乘以 2 的次冪。乘以常數的乘法也可以用一連串的移位和加減法來代替。例如，以下是隻有移位及相加來表示乘以 10 的演演算法。 x 2 x 1 此處是用 x22 x2 來計算 10x x 3 x 1 此處是用 x23 x2 來計算 10x 有時的移位和加減法的組合會比硬體乘法器還快。 若電腦沒有乘法的運算，需要用上述方式來進行計算 Novel Methods of Integer Multiplication and Division by G ReichbornKjennerud，若將向左移位表示為相同的數加二次（兩者在邏輯上等價），也可以延伸到浮點數。 平方的四分之一乘法 可以用平方的算式，計算二個數的乘積，有些來源的算式中會包括取整函式，此方式源自於巴比倫數學（西元前 20001600 年）。 leftlfloor frac left xyright24 rightrfloor leftlfloor frac left xyright24 rightrfloor frac 14left left x22xyy2right left x22xyy2rightright frac 14left 4xyright xy 和為整數，若和中有一個為奇數，另一個也一定會是奇數，因此上式中若有一項在取整數之前有分數，另一項也會有，兩者會相消，不會影響所得的結果。以下是從 0 到 18 計算平方的四分之一取整數的對照表，可以計算以內的乘法： 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 0 0 1 2 4 6 9 12 16 20 25 30 36 42 49 56 64 72 81 若要計算 9 乘 3，其和以及差分別是 12 以及 6，根據上式可得 36 和 9，兩者的差是 27，這就是 9 乘 3 的乘積。 Antoine Voisin 在 1817 年有出版一個平方的四分之一的表，從 1 列到 1000，可以幫助乘法的運算。Samuel Laundy 在 1856 年有出版過 1 到 100000 的表，Joseph Blater 在 1888 年出版了 1 到 200000 的表。 平方的四分之一乘法曾用在模擬計算機上，以形成二訊號相乘的模擬訊號。二個輸入電壓的和或差可以用運算放大器達到。電壓平方可以用電路達成。最後二個平方的四分之一以及兩電壓的差以及再用運算放大器實現。 Everett L Johnson 在 1980 年時提出將此方式應用在數碼乘法器中。為了產生 8 位元整數的乘積，數位裝置計算兩數的和以及差，查表計算平方，計算差值，再往右移位二個位元。 平方的四分之一乘法對 8 位元的系統有益，可以在沒有硬體乘法器的情形下實現乘法。Charles Putney 有將此演演算法實現在 MOS 6502 中。 複數乘法演演算法 複數乘法包括四個實數乘法以及二個加法。 abi cdi acbd bcad i 或 begin arrayccc times a bi hline c ac bci hline di adi bd end array 不過有辦法將實數乘法由四個減少到三個 乘積 a bic di 可以用以下方式計算。 k1 ca b k2 ad c k3 bc d 實部 k1 k3 虛部 k1 k2 此演演算法只用了三個乘法，比原來的四個乘法少一個，但加減法由原來的二個增加到五個。假如乘法的成本遠大於計算加減法的成本，此演演算法的速度會比原來的演演算法快。在現代先進的電腦上，乘法和加法花的時間可能相同，那麼此演演算法就沒有速度上的優勢。若使用浮點數計算，此演演算法可能會有精準度下降的問題，因此需要取捨。 在 FFT（或是其他的線性對映），若是乘以固定係數（c di，在 FFT 中稱為旋轉因子）的複數乘法，其中二個加法（dc 和 cd）可以事先計算，需要即時計算只剩三個乘法以及三個加法 P Duhamel and M Vetterli Fast Fourier transforms A tutorial review and a state of the art Signal Processing vol 19 pp 259299 1990 section 41。不過若是配合有浮點運算器的處理器，加法的速度和乘法相當，因此減少乘法，增加加減法的演演算法，沒有速度上的優勢 S G Johnson and M FrigoA modified splitradix FFT with fewer arithmetic operations IEEE Trans Signal Process vol 55 pp 111119 2007 section IV。 大數字的快速乘法演演算法 Karatsuba 乘法 若需要計算到上千位數字相乘的系統，例如計算機代數系統或高精度計算函式庫，長乘法的速度太慢。因此會使用 Karatsuba 演算法，此乘法演演算法是在 1960 年發現的，在 1962 年出版。此乘法演演算法的精神在於觀察到二位數的乘法可以不用傳統四個乘法的作法，可以只用三個乘法完成。這是分治法的例子。假設要將二個二位數 m 進位數字 x1 m x2 和 y1 m y2 相乘： 計算 x1y1，稱此結果是 F 計算 x2y2，稱此結果是 G 計算 x1 x2y1 y2，稱此結果是 H 計算 H F G，稱此結果是 K，此數字等於 x1y2 x2y1 計算 Fm2 Km G 若要計算三個 m 進位數字的乘積，又可以用上述的技巧，使用遞迴的方式進行（但需要改為其他的進位），此方式。只要計算出乘積數字，再將數字相加，需要 n 個步驟。 Karatsuba 演算法的時間複雜度是 O nlog23 O n1585，此方式明顯的比長乘法要快。因為遞迴產生的額外計算，若 n 較小時，Karatsuba 演算法會比長乘法慢，因此在 n 較小時，會切換回長乘法進行計算。 Karatsuba 演算法是第一個時間複雜度漸進的比長乘法快的演演算法 D Knuth The Art of Computer Programming vol 2 sec 433 1998，也可以視為是快速乘法理論的基礎。 1963 年時，Peter Ungar 建議將 m 改為 i，以產生快速複數乘法的演演算法。若要計算 a b ic d i，可依以下步驟進行： 計算 bd，稱結果為 F 計算 ac，稱結果為 G 計算 a bc d，稱結果為 H 結果的實部是 K H F G ad bc 結果的虛部是 G F ac bd 如同上述複數乘法演演算法所述的一樣，需要三個乘法以及五個加減法。 ToomCook 演算法 另一種乘法的演演算法是 ToomCook 演算法，或稱為 Toom3 演算法。ToomCook 演算法將每一個要相乘的數字切成幾部份，是 Karatsuba 演算法的推廣。三路的 ToomCook 演演算法可以針對大小為 3N 的被乘數和乘數進行乘法，其成本是大小為 N 的被乘數和乘數乘法的 5 倍，因為運算加速的係數是 95，Karatsuba 演算法的加速係數是 43。 若用遞迴的方式將數字分成更多份，可以再縮減計算時間，但位數管理以及加法的成本也會增加。若位數到上千位數，一般會使用傅立葉轉換，速度多半會比較快，若位數更多，傅立葉轉換的優勢更加明顯。 傅立葉變換法 Strassen（1968 年）曾提出用快速多項式乘法來計算快速整數乘法的基本概念。後來在 1971 年由 Strassen 和找到理論和實務的確認，所得的就是 SchönhageStrassen 演演算法 A Schönhage and V Strassen Schnelle Multiplikation großer Zahlen Computing 7 1971 pp 281292。 下限 若用單一處理器將二個 n 進位的數字相乘，時間複雜度有一個 trivial 的下界 Ωn ，沒有更接近實際應用的下界。乘法在以外（p 為任意整數），意思是不存在固定深度，多項式（甚至是次指數）大小，以 AND、OR、NOT、MODp 電路組合成的電路可以計算乘法。Sanjeev Arora and Boaz Barak Computational Complexity A Modern Approach Cambridge University Press 2009。 多項式乘法 上述的乘法演演算法也可以用來計算多項式的乘法。例如 Strassen 演演算法就可以用來計算多項式的乘積。而 也可以將多項式的乘法轉換為二個整數的乘法。 以下是用長乘法來計算多項式乘法的例子： 14ac 3ab 2 乘以 ac ab 1 14ac 3ab 2 ac ab 1 14a2c2 3a2bc 2ac 14a2bc 3 a2b2 2ab 14ac 3ab 2 14a2c2 17a2bc 16ac 3a2b2 5ab 2 相關條目 乘法器 除法器 對數 心算 計算尺 秦九韶演算法，計算多項式的演演算法 參考資料 延伸閱讀 外部連結 基本運算 The Many Ways of Arithmetic in UCSMP Everyday Mathematics A Powerpoint presentation about ancient mathematics Lattice Multiplication Flash Video 進階演演算法 Multiplication Algorithms used by GMP Category 乘法