[英]Fast calculation of floating 1/N if factorization of very large integer N is known
如果我有我知道因式分解的整數N
,那么將1/N
計算為浮點數的最快(最有效)方法是什么? 應該使用大的浮點(或整數)算術。
我想用 C++ 做這個(或者用 Python 做實驗)。
我的N
非常大,大小為 Giga/Tera 位。 結果浮點N
也應該具有很高的精度,大約與初始N
相同的位大小。
需要精確的浮點值,這意味着如果我請求浮點精度Log2(N)
位,那么至少所有95%
的結果前導位都應該是精確的(與理想值中的所有位相同)。
當然,如果它有助於和/或簡化任務,則可以將4^Ceil(Log2(N)) / N
為整數除法,而不是浮點計算。 對我來說,這兩個任務(整數和浮點數)本質上是相同的,因為整數表示可以轉換為浮點數,反之亦然。
一個重要的注意事項是N
因式分解只有很小的質因數,它們的大小都是 32 位(當然最多可能是 64 位)。
我想知道是否有N
因式分解以及因數很小的事實,它能否以某種方式幫助解決任務?
當然,我沒有首先實現我自己的部門,而是嘗試使用高度優化的GMP庫來完成這項任務,但它(據我所知)並沒有使用N
已經被分解的事實。
任何人都可以建議我是否要為此實現自己的功能,只是為了通過實驗確定它是否會比 GMP 更快,那么我應該使用哪種算法?
我發現這里可以使用 3 種算法 1) Long Division ,這是一種學校級算法。 2)巴雷特減少。 3)蒙哥馬利歸約。
其實我不知道任何其他算法。 你能推薦其他的嗎? Barrett 和 Montgomery 歸約只有在相同的素因數重復多次時才有幫助,否則單次除法不值得 Barrett 和 Montgomery 所需的預先計算。
此外,巴雷特/蒙哥馬利的減少仍然需要一次性計算4^Ceil(Log2(N)) / PrimeDivisor
。 所以他們不會讓你免於做長除法算法。
對於長除法算法,我肯定會使用2^64
作為基數而不是基數10
(如在學校中)。
我已經使用 Long Division 和所有其他整數算法以及橢圓曲線算法實現了我自己的實驗庫。 現在它是通用的,因此不比 GMP 快。 現在我需要特殊的除法算法,它至少比 GMP 快幾倍。
當然,在長除法中我可以使用蒙哥馬利和巴雷特,因為在每一步它都需要短除法(128 位整數除以 64 位整數),如果它有任何提升。
同樣在長除法的每個步驟中,我都可以使用快速傅立葉變換或數論變換進行乘法運算。
以上是我所知道的唯一優化。 還有其他可能的優化嗎? 也許FFT可以用於直接做除法(不僅僅是乘法)?
N
可以分解為小整數的事實會有所幫助。 實際上,這意味着N = a1 * a2 * ... * an
。 因此, 1/N = 1/(a1 * a2 * ... * an) = (1/a1) * (1/a2) * ... * (1/an)
。
問題是計算1/a
的許多因素a
可能比計算1/N
快。 的確:
1 / a
的十進制/二進制展開的周期應該遠小於1 / N
因為log2(a)
遠小於log2(N)
這意味着1/a
的精確表示可以以非常緊湊的方式存儲並且很快;然而,有一個問題:這種方法需要很多乘法,因為有很多因子,雖然它們大部分可以並行計算,但這仍然是一個相當昂貴的計算(特別是最后一個乘法很難執行)平行線)。 因此,我不確定該方法是否比在 GMP 中實施的非常優化的方法快得多,但它確實值得一試。
將相同大小的數字相乘或什至將具有最小十進制/二進制擴展周期的第一個數字相乘可能更好(以最小化計算倒數的符號表示的大小,從而導致更小的內存占用和更快的速度)乘法)。
大約有 2 億個素數適合 32 位,但N
大多數因子應該適合 16 位(因為較小的因子更頻繁)並且只有大約 6500 個素數適合 16 位,所以如果您計划計算不同N
多個倒數,則可以預先計算它們的倒數。
當e
很大時,您可以使用平方算法的冪運算來有效地計算p^e
的倒數。 當N
很大時,這樣的項經常以N
的素數分解的指數形式出現。
如果十進制/二進制擴展的周期大於最終浮點數,您可以截斷它。 不過,這可能會影響該方法的准確性。 我認為至少需要一些額外的數字才能獲得准確的結果(特別是由於應用了許多乘法)。
對於涉及巨大符號表示的最后乘法,您可以生成大浮點數並將它們提供給 GMP,以便它可以使用非常優化的實現(通常基於快速傅立葉變換)。
為了清楚起見,這是一個小N = 307230
的示例,使用十進制表示(十進制擴展的周期帶有下划線):
1/307230 = 0.0000032548904729355857175406047586498714318263190443641571461120333300784428603977476157927285746834619015070142889691761872213
------------------------------------------------------------------------------------------------------------------------------
307230 = 2 * 3 * 5 * (7^2) * 11 * 19
1/2 = 0.50
-
1/3 = 0.3
-
1/5 = 0.20
-
1/7 = 0.14285714
------
1/11 = 0.090
--
1/19 = 0.0526315789473684210
------------------
k1 = ((1/2) * (1/3)) * ((1/5) * (1/11)) = 0.0030
--
k2 = k1 * (1/19) = 0.000159489633173843700
------------------
k3 = (1/7)^2 = 0.0204081632653061224489795918367346938775510
------------------------------------------
1/N = k2 * k3
對於最終的乘法,您可以使用精確算法或 GMP 的快速近似。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.