如何解决 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>
我们学习了如何在查找数值的素数因子时解决堆内存溢出错误。每当我们遇到堆内存溢出之类的错误时,都需要像本教程中一样优化我们的代码。
数据结构
网络
关系数据库管理系统 (RDBMS)
操作系统
Java
iOS
HTML
CSS
Android
Python
C语言编程
C++
C#
MongoDB
MySQL
Javascript
PHP