淺談大數除法 Part 2: 快速演算法
前言
要計算兩個大數的乘積,可以先把這兩個大數轉成兩個多項式,計算它們的乘積,再轉回大數,時間複雜度 O(nlogn);然而,大數除法和多項式除法可說是完全不一樣的問題。以下要介紹如何利用牛頓法把除法問題轉化成乘法問題,並利用倍增 (doubling) 來得到 O(nlogn) 的除法演算法。本文內容大致上只是把之前我寫的這篇 document 換成中文,但一些證明以及虛擬碼 (pseudocode) 則省略。另,實作部分可以參考我在 github 上的大數模板,讀者也可以在 ZJ b960 測試自己的程式。
動機
以下設 ξ 和 η 都是 A 進位正整數,其中 A≥9,ξ≥η,且 ξ 和 η 的長度分別為 m 和 n,目標求出 ⌊ξ/η⌋ 的 A 進位表示。因為 ξ/η=ξ×1/η 如果我們能把 1/η 算得夠精確,就能把除法問題轉換成乘法問題。我們希望能找到某個 x≤1/η 使得 ⌊ξ/η⌋−1≤⌊ξx⌋≤⌊ξ/η⌋ 不難發現只要 x 滿足 0≤1/η−x≤A−m 就有 ξ/η−ξx=ξ(1/η−x)≤Am⋅A−m=1 也就是 (1) 會成立。接下來我們把目標放在找到 x 滿足 (2)。牛頓法
考慮函數 f(x):=1x−η。我們找一個 x0∈(0,1η],並對於所有的 k≥0,令 xk+1←xk−f(xk)f′(xk)=xk(2−ηxk) 引入 ϵk:=1−ηxk,則我們有 ϵk+1=1−ηxk(2−ηxk)=(1−ηxk)2=ϵ2k (3) 告訴我們,如果某個 k0 滿足 ϵk0≤A−1,則對任意 l≥0 都有 ϵk0+l≤A−2l,收斂速度相當快。捨去低位與倍增
(3) 看起來很棒,可是實際上我們不可能在每次迭代都算出 xk 的精確值 (不然時間複雜度還是會壞掉),必須捨去低位並重新估計誤差收斂速率。把 (2) 重寫成 An−1η−An−1x≤A−(m−n+1) 為了方便,我們 (暫時) 重新設 η←η/An−1 並設 x←An−1x,這樣一來 (4) 就被簡化成 1η−x≤A−(m−n+1) 注意這樣一來就有 1≤η<A,因此要滿足 (5),只要找到 x 使得 2(1−ηx)≤A−(m−n+1) 就行了。性質一:設 h 為 η 的最高兩位 (如當 A=10 且 η=1.234 時,h=12),取 x0=⌊A3h+1⌋A−2,則
- x0≤1η
- 2ϵ0:=2(1−ηx0)≤A−1/2
- xk−1≤1η
- 2ϵk−1≤A−2k−2
- 令 yk 為把 η 無條件進位至小數第 2k−1+1 位的結果
- 令 zk 為把 ykxk−1 無條件進位至小數第 2k−1+1 位的結果
- 令 xk 為把 xk−1(2−zk) 無條件捨去至小數第 2k−1+3 位的結果
- xk≤1η
- 2ϵk≤A−2k−1
留言
張貼留言