我實施了Karatsuba乘法算法來達到我的教育目標。現在我正在尋找更多的改進。我已經實現了某種長算術,並且它能夠很好地工作,不管我使用的整數表示的基數是否超過。 含底座和範圍[10^50000, 10^50001]
與clang++ -O3
乘兩個隨機整數編譯需要:Karatsuba乘法改進
Naive algorithm took me 1967 cycles (1.967 seconds)
Karatsuba algorithm took me 400 cycles (0.4 seconds)
而基礎相同的數字:
Naive algorithm took me 409 cycles (0.409 seconds)
Karatsuba algorithm took me 140 cycles (0.14 seconds)
是否有改善的方法這個結果? 現在我使用這些函數來完成我的結果:
void finalize(vector<int>& res) {
for (int i = 0; i < res.size(); ++i) {
res[i + 1] += res[i]/base;
res[i] %= base;
}
}
正如你可以看到它進行計算,並把它推到下一個數字的每一步。如果我以>=1000
爲基數,結果將會溢出。
如果您在我的代碼中看到我使用int向量來表示長整數。根據我的基數,一個數字將分成不同的部分。 現在我看到幾個選項:
- 使用
long long
類型載體,但它可能也將被溢出了廣大長度整數 - 實現長期算術
隨身攜帶的表示我參觀過之後我決定擴大這個問題。假設我們想要將我們的長整數表示爲一個整數的向量。對於instanse:
ULLONG_MAX = 18446744073709551615
而對於輸入我們通過第210號Fibonacci數34507973060837282187130139035400899082304280
不適合任何類型stadard。如果我們在基礎千萬爲int的矢量代表它就會像:
v[0]: 2304280
v[1]: 89908
v[2]: 1390354
v[3]: 2187130
v[4]: 6083728
v[5]: 5079730
v[6]: 34
當我們做乘法,我們可能會(爲簡單起見,讓它成爲兩個相同的數字) (34507973060837282187130139035400899082304280)^2
:
v[0] * v[0] = 5309706318400
...
v[0] * v[4] = 14018612755840
...
這只是第一行,我們必須做這六個步驟。當然,某些步驟會在乘法或進位計算後引起溢出。
如果我錯過了什麼,請告訴我,我會改變它。 如果你想看到完整的版本,它是我的github
如果你有工作代碼,那麼也許你的問題更適合http://codereview.stackexchange.com/? – EdChum
我投票結束這個問題作爲題外話,因爲它屬於codereview。在那裏,你需要在你的帖子中發佈代碼,而不是鏈接到你的github。你只需要發佈相關的部分。 – UmNyobe
如果你真的想加速,那麼你應該使用另一種更快的算法:例如Toom-Cook或者傅立葉變換。 –