素數的概念大家都知道,就是指只能被1和它本身整除的自然數。假如我們要找1-100之間的素數該怎么辦呢?一個眼前的方法就是從2開始,每個數都試試能否被其他數整除。一旦發現1-100之間的素數,我們就會發現找素數可不是個簡單的任務。但是在JavaScript中,有一些很巧妙的方法可以幫我們更高效地找出素數中的牛鼻子,下面就跟大家分享一下吧。
最基礎的素數判斷方法就是從2開始,一直到sqrt(n)為止進行遍歷。當n % i === 0時,n就不是素數了,因為n可以被i整除。這是因為函數中sqrt函數只遍歷到該數字的平方根,因為在平方根后的除數必定是前面出現過的。這么做的時間復雜度為O(根號n)。
function isPrime(n) { if (n <= 1) return false; //判斷是否小于2,因為小于2的數都不是素數 const max = Math.sqrt(n); //計算最大可遍歷的數 for (let i = 2; i <= max; i++) { if (n % i === 0) return false; //如果n能被i整除,則n不是素數 } return true; }
然而,我們可以進一步優化。若一個數不是素數,則它可以表示成兩個數的成積的形式,并且兩個數中必有一個小于等于該數的平方根。那么,在判斷n是否為素數時,我們可以只遍歷到其平方根的整數部分,而不需要枚舉到n的所有因數。這樣可以減少循環次數,進一步優化時間復雜度,假設n為大素數,則這個速度就可以驚人到O(根號m),因為小于根號m的已經夠用了,所以就不需要再遍歷了。
function isPrime(n) { if (n <= 1) return false; const max = Math.floor(Math.sqrt(n)); //向下取整 for (let i = 2; i <= max; i++) { if (n % i === 0) return false; } return true; }
以上方法雖然比前面的優化一些,但是還是會出現很大的整數進行計算時出現超時的情況,這時候就需要用到另外一種方法——埃氏篩法。所以在此,我們就需要理解下埃氏篩法。
埃氏篩法又稱質數篩法,是尋找一定范圍內的素數的一種簡單而又高效的做法。它的基本思想是:從2開始,將每個質數的倍數都標記成合數、已知2是素數,就把2的倍數都標記成合數(即非素數),然后再找下一個的素數——即沒有被標記過的最小的數,然后再把它的倍數全都標記成合數,以此類推……直到篩子不能篩為止。
function getPrimes(n) { const isPrime = new Array(n + 1).fill(true); isPrime[0] = false; isPrime[1] = false; const max = Math.floor(Math.sqrt(n)); //向下取整 for (let i = 2; i <= max; i++) { if (isPrime[i]) { for (let j = i * i; j <= n; j += i) { isPrime[j] = false; } } } return isPrime.reduce((acc, curr, idx) => { if (curr) acc.push(idx); return acc; }, []); }
以上是常見的找素數方法,如果需要使用到中大型的數據計算時,使用埃氏篩法會更加高效的解決問題,而對于非常大數的情況下可以使用Miller-Rabin素數檢測法進行優化,因為Miller-Rabin算法的時間復雜度另外一種的方法就感覺大大降低了。
總結下,在JavaScript中,找素數的方法共有三種,分別是遍歷法、優化法和埃氏篩法,如果再需要提高時間效率,那么可以使用Miller-Rabin素數檢測法進行多次計算再進行取中值的優化,只要靈活運用這三中方法,就可以輕松地找到你想要的素數啦!