web-dev-qa-db-ja.com

Javascriptでforループを使用して素因数を見つける方法は?

私はjavascriptを初めて使用し、javascriptのforループを使用して、以下に「整数」として記録されている数の素因数を見つけようとしていました。私はそれを機能させることができないようで、それが私のjavascriptなのか計算ロジックなのかわかりません。私が自分のプログラムがその時点で何をしていると思うかがわかるように、コメントを追加しようとしました。私が間違っている場合は私を訂正してください。

どんな助けでもありがたいです。これが私のコードです:

//integer is the value for which we are finding prime factors
var integer = 13195;

var primeArray = [];

//find divisors starting with 2

for (i = 2; i < integer/2; i++) {
  if (integer % i == 0) {

    //check if divisor is prime
    for (var j = 2; j <= i / 2; j++) {
      if (i % j == 0) {
        isPrime = false;
      } else {
        isPrime = true;
      }
    }

    //if divisor is prime

    if (isPrime == true) {
      //divide integer by prime factor & factor store in array primeArray
      integer /= i
      primeArray.Push(i);
    }
  }
}

for (var k = 0; k < primeArray.length; k++) {
  console.log(primeArray[k]);
}
8
John the User

実用的な解決策は次のとおりです。

//integer is the value for which we are finding prime factors
var integer = 13195,
    primeArray = [],
    isPrime;

//find divisors starting with 2

for(i = 2; i <= integer; i++){
  if (integer % i==0) {

    //check if divisor is prime
    for(var j = 2; j <= i/2; j++) {
      if(i % j == 0) {
        isPrime = false;
      } else {
        isPrime = true;
      }
    }

    //if the divisor is prime

    if (isPrime == true) {
      //divide integer by prime factor & factor store in array primeArray
      integer /= i
      primeArray.Push(i);
    }
  }   
}

for (var k = 0; k < primeArray.length; k++) {
  console.log(primeArray[k]);
}

あなたは非常に正しい方向に進んでいました。 2つの小さな間違いがありました。 integer - 1の評価が間違っているようです。より適切な評価は、外側のforループの<= integerだと思います。これは、整数をinteger /= i未満で除算すると、最終的な整数評価が29になるためです。この場合の最後の主除数も29であるため、<=ではなく< integer - 1として評価する必要があります。

最後のログステートメントが機能しない理由については、primeArray[i]とは対照的にprimeArray[k]の単純なタイプミスがありました。

7
War10ck

上記の両方のコードに間違いがあると思います。整数を100に置き換えると、因数2はforループとは見なされないため、素因数分解は機能しなくなります。条件でj = 2、i = 2、j <= i/2であるため、ループは素因数であるi = 2では実行されません。

このように機能させようとしましたが、理解できませんでした。

ここでwhileループを使用した別のアプローチに依存する必要がありました:

    function getAllFactorsFor(remainder) {
    var factors = [], i;

    for (i = 2; i <= remainder; i++) {
        while ((remainder % i) === 0) {
            factors.Push(i);
            remainder /= i;
        }
    }

    return factors;
}

https://jsfiddle.net/JamesOR/RC7SY/

あなたはそのようなもので行くこともできます:

let findPrimeFactors = (num) => {
    let arr = [];


    for ( var i = 2; i < num; i++) {
        let isPrime
        if (num % i === 0) {
            isPrime = true;
            for (var j = 2; j <= i; j++) {
                if ( i % j === 0) {
                isPrime == false;
                }
            } 
        }if (isPrime == true) { arr.Push(i)}

    }console.log(arr)
}

findPrimeFactors(543)
7

上記の答えは、O(N ^ 2)の複雑さでは非効率的です。ここにO(N)複雑さを伴う)より良い答えがあります。

function primeFactors(n){
  var factors = [], 
      divisor = 2;

  while(n>2){
    if(n % divisor == 0){
       factors.Push(divisor); 
       n= n/ divisor;
    }
    else{
      divisor++;
    }     
  }
  return factors;
}

必要に応じて重複をフィルタリングできます。

4
Alan Judi

一番下から作業を進める場合、次の要素が素数であるかどうかを確認する必要はありません。これは、下の素数がすでに分割されているためです。

function getPrimeFactorsFor(num) {
  const primes = [];
  for (let factor = 2; factor <= num; factor++) {
    while ((num % factor) === 0) {
      primes.Push(factor);
      num /= factor;
    }
  }
  return primes;
}


console.log("10 has the primes: ", getPrimeFactorsFor(10));
console.log("8 has the primes: ", getPrimeFactorsFor(8));

console.log("105 has the primes: ", getPrimeFactorsFor(105))
console.log("1000 has the primes: ", getPrimeFactorsFor(1000))
console.log("1155 has the primes: ", getPrimeFactorsFor(1155))
1
apollovishwas

私の解決策は、素因数ではないものを返すことを避けます:

let result = [];
let i = 2;
let j = 2;
let number = n;

for (; i <= number; i++) {
    let isPrime = number % i === 0;
    if (isPrime) {
        result.Push(i);
        number /= i;
    }
    while (isPrime) {
        if (number % i === 0) {
            result.Push(i);
            number /= i;
        } else {
            isPrime = false;
        }
    }
}

return result;
0
Hmorv

上記の非常に多くの優れたソリューションで、数学フォーラムでこの定理を使用して少し改善したいと思いました 平方根を取ることによって素因数を見つける

function primeFactors(n) 
{ 
    // Print the number of 2s that divide n 
    while (n%2 == 0) 
    { 
        console.log(2); 
        n = n/2; 
    } 
  
    // n must be odd at this point.  So we can skip  
    // one element (Note i = i +2) 
    for (var i = 3; i <= Math.sqrt(n); i = i+2) 
    { 
        // While i divides n, print i and divide n 
        while (n%i == 0) 
        { 
            console.log(i); 
            n = n/i; 
        } 
    } 
  
    // This condition is to handle the case when n  
    // is a prime number greater than 2 
    if (n > 2) 
        console.log(n);
}

primeFactors(344);
console.log("--------------");
primeFactors(4);
console.log("--------------");
primeFactors(10);

この答えが付加価値をもたらすことを願っています。

0
capote1789

これが再帰を使用した解決策です

function primeFactors(num, primes){
  let i = 2;
  while(i < num){
    if(num % i === 0){
      primes.Push(i);
      return primeFactors(num/i, primes);
    }
    i++
  }
  primes.Push(num);
  return primes;
}

console.log(primeFactors(55, []))
console.log(primeFactors(15, []))
console.log(primeFactors(40, []))
console.log(primeFactors(13, []))
// [ 5, 11 ]
// [ 3, 5 ]
// [ 2, 2, 2, 5 ]
// [ 13 ]
0
AZ SH

私はJavaScriptを開始したばかりですが、同じような目的で学校のプロジェクトに取り組んでいる間に、独自の解決策を考え出すことができました。

唯一の問題は、多数の場合は非常に長い時間がかかり、あまり効率的ではないということです。しかし、それは完全に機能します。

function isPrime(n){
if (n === 1){
  return false;
}
  else if (n === 2){
    return true;
  }
  else{
  for (let x = 2; x < n; x ++){
    if (n % x === 0){
      return false;
    }
  }
    return true;
}
}

let primeFac = []
let num = 30
for (let x = 0; x <= num; x++){
  if (num % x === 0 && isPrime(x) === true){
primeFac.Push(x);
  }
}
console.log(`${primeFac}`)
0
Flaming_Dorito

上記のコード(whileループを持つコード)は正しいですが、そのコードには小さな修正が1つあります。

var num, i, factorsArray = [];

function primeFactor(num) {
  for (i = 2; i <= num; i++) {
    while (num % i == 0) {
      factorsArray.Push(i);
      num = num / 2;
    }
  }
}
primeFactor(18);
var newArray = Array.from(new Set(factorsArray));
document.write(newArray);
0
Vinayaka B R

ここでは、3つのバリエーションで素因数を見つけるための他の実装を示します。他の実装、最悪の場合sqrt(n)よりも効率的です。これは、より早く停止するためです。

function*ジェネレーター関数 であることを意味します。したがって、配列の代わりにジェネレータが返され、次の素因数は要求されたときにのみ計算されます。

// Example: 24 -> 2, 3
function* singlePrimeFactors (n) {
    for (var k = 2; k*k <= n; k++) {
        if (n % k == 0) {
            yield k
            do {n /= k} while (n % k == 0)
        }
    }
    if (n > 1) yield n
}

// Example: 24 -> 2, 2, 2, 3
function* repeatedPrimeFactors (n) {
    for (var k = 2; k*k <= n; k++) {
        while (n % k == 0) {
            yield k
            n /= k
        }
    }
    if (n > 1) yield n
}

// Example: 24 -> {p: 2, m: 3}, {p: 3, m: 1}
function* countedPrimeFactors (n) {
    for (var k = 2; k*k <= n; k++) {
        if (n % k == 0) {
            var count = 1
            for (n /= k; n % k == 0; n /= k) count++
            yield {p: k, m: count}
        }
    }
    if (n > 1) yield {p: n, m: 1}
}

// Test code
for (var i=1; i<=100; i++) {
    var single = JSON.stringify(Array.from(singlePrimeFactors(i)))
    var repeated = JSON.stringify(Array.from(repeatedPrimeFactors(i)))
    var counted = JSON.stringify(Array.from(countedPrimeFactors(i)))
    console.log(i, single, repeated, counted)
}

// Iterating over a generator
for (var p of singlePrimeFactors(24)) {
    console.log(p)
}

// Iterating over a generator, an other way
var g = singlePrimeFactors(24)
for (var r = g.next(); !r.done; r = g.next()) {
    console.log(r.value);
}
0
user42723