Stackoverflow:計算兩個整數(shù)的最小公倍數(shù)的最有效方法是什么?
一、前言
嘿,小傅哥怎么突然講到最大公約數(shù)了?
這么想你肯定是沒有好好閱讀前面章節(jié)中小傅哥講到的RSA算法,對于與歐拉結(jié)果計算的互為質(zhì)數(shù)的公鑰e,其實就需要使用到輾轉(zhuǎn)相除法來計算出最大公約數(shù)。
放心,你所有寫的代碼,都是對數(shù)學(xué)邏輯的具體實現(xiàn),無非是難易不同罷了。所以如果你真的想學(xué)好編程思維而不只是CRUD,那就要把數(shù)據(jù)結(jié)構(gòu)、算法邏輯等根基打牢。
二、短除法
既然都說到這了,那你還記得怎么計算最大公約數(shù)嗎,死鬼?
以上這種方式就是我們在上學(xué)階段學(xué)習(xí)的,這種計算方式叫做短除法。
短除法:是算術(shù)中除法的算法,將除法轉(zhuǎn)換成一連串的運算。短除法是由長除法簡化而來,當中會用到心算,因此除數(shù)較小的除法比較適用短除法。對大部分的人而言,若除以12或12以下的數(shù),可以用記憶中乘法表的內(nèi)容,用心算來進行短除法。也有些人可以處理除數(shù)更大的短除法?!?來自維基百科
三、歐幾里德算法
短除法能解決計算最大公約數(shù)的問題,但放到程序編寫中總是很別扭,總不能一個個數(shù)字去試算,這就顯得很鬧挺。其實除了短除法還有一種是計算公約數(shù)的辦法,叫做歐幾里德算法。
歐幾里德算法:是計算兩個整數(shù)(數(shù)字)的最大公約數(shù)【GCD(Greatest Common Divisor)】的有效方法,即能將它們整除而無余數(shù)的最大數(shù)。它以古希臘數(shù)學(xué)家 歐幾里得的名字命名,歐幾里德在他的幾何原本(約公元前 300 年)中首次描述了它。它是算法的示例,是根據(jù)明確定義的規(guī)則執(zhí)行計算的分步過程,并且是常用的最古老的算法之一。它可以用來減少分數(shù)到他們的最簡單的形式,并且是許多其他數(shù)論和密碼計算的一部分?!?來自維基百科
GCD,代表了兩個數(shù)字的最大公約數(shù),GCD(X,Y) = Z,那么就表示 X 和 Y 的最大公約數(shù)是 Z。由歐幾里德算法給出 GCD(X,Y) = GCD(Y,XmodY) —— mod 表示求模計算余數(shù)。
其實簡單來說就是,X和Y的公約數(shù)是Z,那么Y和Z的公約數(shù)也是Z。24和18的最大公約數(shù)是6,那么18和6的公約數(shù)也是6。嘿,就這么一個事。但就因為有了這一樣一條推論,讓編程代碼變得優(yōu)雅舒服,只需要不斷地將X、Y兩數(shù)作差,就能計算最大公約數(shù)。
這讓小傅哥想起,多年前上學(xué)時候,我也給出過一條推論;”任意一組所能構(gòu)成等差數(shù)列的三個數(shù)字,所能組合出來的一個三位數(shù),都能被3整除?!?例如:等差數(shù)列 16、31、46 組合成三位數(shù) 463116 或者 461631 都能被3整除。
四、輾轉(zhuǎn)相除法代碼實現(xiàn)
歐幾里德算法 = 輾轉(zhuǎn)相除法法:https://en.wikipedia.org/wiki/Euclidean_algorithm
在輾轉(zhuǎn)相除法的實現(xiàn)中,計算最大公約數(shù)的方式,就是使用一個數(shù)字減去另外一個數(shù)字,直到兩個數(shù)字相同或者有其中一個數(shù)字為0,那么最后不為零的那個數(shù)字就是兩數(shù)的最大公約數(shù)。
小傅哥在這里提供了2種計算方式,一種是循環(huán)另外一種是遞歸?!?方便很多看不懂遞歸的小伙伴可以用另外的方式學(xué)習(xí)。
1. 循環(huán)實現(xiàn)
- 兩數(shù)循環(huán)處理中,條件為 m != 0 && n != 0 && m != n直至循環(huán)結(jié)束。
2. 遞歸實現(xiàn)
- 計算方式邏輯和條件是一樣的,只不過這個是使用了遞歸調(diào)用的方式進行處理。
3. 測試驗證
測試結(jié)果
- 計算 124 和 20 的最大公約數(shù),兩個計算方式結(jié)果都是 4 。好的,到這測試通過。
- 這并不是一個很難的知識點,但當你做一些技術(shù)分享、答辯述職等時候,能這樣用技術(shù)語言而不是大白話的講述出來后,其實高度就有了。兄弟!
在 stackoverflow.com 看到一道問題:計算兩個整數(shù)的最小公倍數(shù)的最有效方法是什么?
乍一看, 這能有啥。不就是計算下最小公倍數(shù)嗎?但一想我腦袋中計算最小公倍數(shù)的方法;一種是在本子上通過短除法計算,另外一種是基于計算出的最大公約數(shù),再使用公式:lcm(a, b) = |a * b| / gcd(a, b) 求得最小公倍數(shù)?!?計算最大公約數(shù)是基于歐幾里德算法(輾轉(zhuǎn)相除法)
那么這樣的計算方法是不是最有效的方法,另外如果是同時計算多個整數(shù)的最小公倍數(shù),要怎么處理?
其實編程的學(xué)習(xí)往往就是這樣,留心處處都是學(xué)問,你總是需要從各種細小的點中,積累自己的技術(shù)思維廣度和縱向探索深度。好啦,接下來小傅哥就給大家介紹幾種用于計算最小公倍數(shù)的算法。
五、用公約數(shù)實現(xiàn)
公式:lcm(a, b) = |a * b| / gcd(a, b)
- 首先這里是一個比較簡單的方式,基于兩數(shù)乘積除以最大公約數(shù),得到的結(jié)果就是最小公倍數(shù)。
六、簡單累加計算
此計算方式為,在一組正整數(shù)數(shù)列中,通過找到最小的數(shù)字進行自身累加循環(huán),直至所有數(shù)字相同時,則這個數(shù)字為最小公倍數(shù)?!?你能代碼實現(xiàn)一下嗎?
- 在代碼實現(xiàn)中,首先要把n個整數(shù)數(shù)列進行克隆保存。因為每次相加的都是最初的這個數(shù)列里的數(shù)字值。接下來就是以所有數(shù)字都相等作為條件循環(huán)判斷,不斷地的累加最小的數(shù)值即可。最終返回的就是最小公倍數(shù)。
七、表格推演計算
表格計算方式為將一組數(shù)字以最小的質(zhì)數(shù)2開始整除,直到不能被2整除后,用下一個質(zhì)數(shù)3繼續(xù)整除(剩余的數(shù)字中比大的最小的質(zhì)數(shù))直至所有數(shù)字都為1的時候結(jié)束。最終所有有效的質(zhì)數(shù)乘積就是最小公倍數(shù)。—— 想想如果這讓你用代碼實現(xiàn),你能肝出來嗎?
- 在代碼實現(xiàn)中我們通過 Map 作為表的key,Map 中的 List 作為表每一行數(shù)據(jù)。通過這樣一個結(jié)構(gòu)構(gòu)建出一張表。
- 接下來以所有元素最后一位為1作為條件循環(huán)處理數(shù)據(jù),用最開始的2作為素數(shù)整除列表中的數(shù)據(jù),并保存到下一組數(shù)列中。當2不能整除時,則刷新素數(shù),選取另外一個列表中最小的素數(shù)作為除數(shù)繼續(xù)。
- 這個過程中會累計有效素數(shù)的乘積,這個乘積的最終結(jié)果就是最小公倍數(shù)。
八、測試驗證
單元測試
測試結(jié)果
- 到這里測試就結(jié)束了,本章一共介紹了三種計算最小公倍數(shù)的方法。那如果只讓你看到邏輯,你能寫出最終的代碼嗎?
九、常見面試
- 最大公約數(shù)的使用用途?
- 如何使用代碼實現(xiàn)最大公約數(shù)計算?
- 你是否了解歐幾里德算法?
- 關(guān)于數(shù)論你還記得多少?
- RSA 加密算法為什么需要用到公約數(shù)計算?
- 如何計算兩數(shù)的最小公倍數(shù)?
- 如果計算多個整數(shù)的最小公倍數(shù)?
- 你能說一下具體如何實現(xiàn)這種X的計算流程嗎?
- 你知道最小公倍數(shù)計算的用途嗎?
- What is the most efficient way to calculate the least common multiple of two integers?:https://stackoverflow.com/questions/3154454/what-is-the-most-efficient-way-to-calculate-the-least-common-multiple-of-two-int/3154503#3154503
- Least common multiple:https://en.wikipedia.org/wiki/Least_common_multiple
- Chebyshev function:https://en.wikipedia.org/wiki/Chebyshev_function
- 歐幾里德算法:https://en.wikipedia.org/wiki/Euclidean_algorithm
- 線性組合:https://en.wikipedia.org/wiki/Linear_combination
- 貝祖定理:https://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity?