如何解決 JavaScript 堆記憶體溢位問題(關於素數)


正如“堆記憶體溢位”錯誤資訊所提示的那樣,當任何 JavaScript 程式碼使用的記憶體超過分配的記憶體時,就會發生這種情況。當我們執行任何 JavaScript 程式時,計算機都會為該 JavaScript 程式分配特定的記憶體。

當我們執行 JavaScript 程式碼或任何程式語言的程式碼時,我們的計算機都會建立一個程序並分配固定大小的記憶體。當程式需要更多記憶體時,就會引發堆記憶體溢位之類的錯誤。例如,如果我們建立一個大小為 1020 的陣列,並嘗試使用某些值初始化每個陣列索引,則堆記憶體會溢位並引發錯誤。

在本教程中,我們將學習如何解決在查詢非常大量的數值的素數因子時出現的 JavaScript 堆記憶體溢位問題。

使用者可以按照下面的示例來直觀地瞭解堆記憶體溢位錯誤。

示例(直觀瞭解錯誤)

在下面的示例中,我們建立了 getPrimeFactors() 函式,該函式返回任何數值的素數因子。當我們傳遞較小的數值(接近 103)時,它執行良好,但是當我們傳遞較大的數值(接近 109)作為引數來查詢素數因子時,它會報錯,瀏覽器視窗會變成黑屏。

在此示例中,記憶體錯誤是由於我們使用兩個巢狀迴圈來迭代陣列,程式的時間複雜度變為 O(N2),這會佔用超過分配記憶體的記憶體。

<html>
<body>
   <h2>Visualizing the <i>Process out of memory</i> while finding all prime factors of a number in JavaScript </h2>
</body>
<script>
   try {
      function getPrimeFactors(num) {
         var factor = []; 
         let primes = [];
         for (let m = 2; m <= num; m++) {
            if (!factor[m]) {
               primes.push(m);
               for (let n = m << 1; n <= num; n += m) {
                  factor[n] = true;
               }
            }
         }
         return primes;
      }
      getPrimeFactors(1212121212323)
   } catch (err) {
      console.log(err.message)
   }
</script>
</html>

在上例的輸出中,使用者可以看到堆記憶體溢位錯誤。要解決此問題,我們需要最佳化程式碼的時間和空間複雜度。

下面,我們將最佳化示例 1 中編寫的程式碼的時間複雜度,以查詢給定數字的所有唯一素數因子。

語法

使用者可以按照下面的語法編寫最佳化的程式碼,以查詢給定數值的唯一素數因子。

for (let m = 2; m * m <= value; m++) {
   if (value % m === 0) {
      
      // store factor to array
      while (value % m === 0) {
         value /= m;
      }
   }
}
if (value > 2) {
   
   // store factor to array
}

在上面的語法中,我們使用 for 迴圈進行迭代,直到 m*m 小於該值。這意味著我們進行迭代,直到該值的平方根大於 m。

步驟

步驟 1 − 使用 for 迴圈進行迭代,直到值的平方根大於 m,其中 m 是 for 迴圈的初始化變數。

步驟 2 − 在 for 迴圈中,如果值可以被 m 整除,則表示 m 是該值的素數因子,並將其儲存在因子陣列中。

步驟 3 − 之後,使用 while 迴圈將值除以 m,如果值可以被 m 多次整除,則多次除以 m。這裡,我們需要儲存唯一的素數因子,因此我們只將 m 的值儲存到陣列中一次。

步驟 4 − for 迴圈的所有迭代完成後,檢查值是否大於 2。如果是,則表示該值是最大的素數因子,並將其儲存到陣列中。

示例(解決錯誤)

下面的示例使用陣列來儲存素數因子。此外,我們還實現了上述演算法來查詢素數因子。

使用者可以嘗試查詢大型數值(例如 1020)的唯一素數因子,並檢視程式碼是否能無錯誤地輸出結果。

<html>
<body>
   <h2>Solving the <i> Process out of memory </i> while finding all prime factors of a number in JavaScript</h2>
   <div id = "output"> </div>
</body>
<script>
   let output = document.getElementById('output');
   function getPrimeFactors(value) {
      let initial = value;
      var factors = [];
      for (let m = 2; m * m <= value; m++) {

         // if the value is divisible by m, it is a prime factor
         if (value % m === 0) {
            factors.push(m);

            // divide value by m until it is divisible
            while (value % m === 0) {
               value /= m;
            }
         }
      }

      // push largest prime factor at last
      if (value > 2) {
         factors.push(value); 
      }
      output.innerHTML += "The prime factors of " + initial + " are : " + factors + "<br/>";
   }
   getPrimeFactors(100000000002);
   getPrimeFactors(65416841658746141122);
</script>
</html>

示例

在下面的示例中,我們使用集合來儲存素數因子,而不是使用陣列,因為我們需要獲得唯一的素數因子。此外,我們還使用 for-of 迴圈來列印儲存在集合中的所有素數因子。

<html>
<body>
   <h2>Solving the <i> Process out of memory </i> while finding all prime factors of a number in JavaScript</h2>
   <div id = "output"> </div>
</body>
<script>
   let output = document.getElementById('output');
   function getPrimeFactors(value) {
      let initial = value;
      var factors = new Set();
      for (let m = 2; m * m <= value; m++) {
         if (value % m === 0) {
            factors.add(m);
            while (value % m === 0) {
               value /= m;
            }
         }
      }
      if (value > 2) {
         factors.add(value);
      }
      output.innerHTML += "The prime factors of " + initial + " are : <br/>";

      // print values of a set
      for (let fac of factors) {
         output.innerHTML += fac + "<br/>";
      }
   }
   getPrimeFactors(44352747207453165);
</script>
</html> 

我們學習瞭如何在查詢數值的素數因子時解決堆記憶體溢位錯誤。每當我們遇到堆記憶體溢位之類的錯誤時,都需要像本教程中一樣最佳化我們的程式碼。

更新於:2023年2月22日

瀏覽量:193

啟動您的職業生涯

透過完成課程獲得認證

開始學習
廣告