淺談大數除法 Part 2: 快速演算法

前言

要計算兩個大數的乘積,可以先把這兩個大數轉成兩個多項式,計算它們的乘積,再轉回大數,時間複雜度 O(nlogn);然而,大數除法和多項式除法可說是完全不一樣的問題。以下要介紹如何利用牛頓法把除法問題轉化成乘法問題,並利用倍增 (doubling) 來得到 O(nlogn) 的除法演算法。

本文內容大致上只是把之前我寫的這篇 document 換成中文,但一些證明以及虛擬碼 (pseudocode) 則省略。另,實作部分可以參考我在 github 上的大數模板,讀者也可以在 ZJ b960 測試自己的程式。

動機

以下設 ξη 都是 A 進位正整數,其中 A9ξη,且 ξη 的長度分別為 mn,目標求出 ξ/ηA 進位表示。因為 ξ/η=ξ×1/η 如果我們能把 1/η 算得夠精確,就能把除法問題轉換成乘法問題。我們希望能找到某個 x1/η 使得 ξ/η1ξxξ/η 不難發現只要 x 滿足 01/ηxAm 就有 ξ/ηξx=ξ(1/ηx)AmAm=1 也就是 (1) 會成立。接下來我們把目標放在找到 x 滿足 (2)

牛頓法

考慮函數 f(x):=1xη。我們找一個 x0(0,1η],並對於所有的 k0,令 xk+1xkf(xk)f(xk)=xk(2ηxk) 引入 ϵk:=1ηxk,則我們有 ϵk+1=1ηxk(2ηxk)=(1ηxk)2=ϵ2k (3) 告訴我們,如果某個 k0 滿足 ϵk0A1,則對任意 l0 都有 ϵk0+lA2l,收斂速度相當快。

捨去低位與倍增

(3) 看起來很棒,可是實際上我們不可能在每次迭代都算出 xk 的精確值 (不然時間複雜度還是會壞掉),必須捨去低位並重新估計誤差收斂速率。把 (2) 重寫成 An1ηAn1xA(mn+1) 為了方便,我們 (暫時) 重新設 ηη/An1 並設 xAn1x,這樣一來 (4) 就被簡化成 1ηxA(mn+1) 注意這樣一來就有 1η<A,因此要滿足 (5),只要找到 x 使得 2(1ηx)A(mn+1) 就行了。

性質一:hη 的最高兩位 (如當 A=10η=1.234 時,h=12),取 x0=A3h+1A2,則
  1. x01η
  2. 2ϵ0:=2(1ηx0)A1/2
性質二:k1。假定 xk1 滿足
  1. xk11η
  2. 2ϵk1A2k2

  1. yk 為把 η 無條件進位至小數第 2k1+1 位的結果
  2. zk 為把 ykxk1 無條件進位至小數第 2k1+1 位的結果
  3. xk 為把 xk1(2zk) 無條件捨去至小數第 2k1+3 位的結果

  1. xk1η
  2. 2ϵkA2k1
根據上面兩個性質,我們只要用上面的構造方式,執行迭代直到 2k1mn+1,就能取 xxk 以滿足 (6)。

時間複雜度分析

由於 T(m)=T(m2)+O(mlogm)=O(mlogm),時間複雜度和乘法一樣,但常數大上許多。

留言

這個網誌中的熱門文章

2020 全國賽驗題心得

水母上 Divide-and-Conquer

109 學年度全國資訊學科能力競賽各題詳解