2016-11-04 11 views
0

長いループが10分以上かかることがありますが、これを避けるために常に新しい時間を設定したいと思います。しかし、それは動作しません。JS - "クラッシュ"ブラウザの実装からの長いループのJavaScriptを防止する

私はそれが動作problem3()関数で console.log(Date() - t);を入れて、私は()日付を行うことができない場合は
function problem3(){ 
       var img = document.getElementById('p_3'); 
       img.style.display = img.style.display === 'block' ? 'none' : 'block'; 
       var number=600851475143; 
       var t = new Date(); 
       for(var i=3;i*i<=number;i+=2){ 
        if(isPrime(i) && number%i==0){ 
         var maxPrime = i; 
        } 
        setInterval(function(){time(t)},5000); 
       } 
       document.getElementById("p3").innerHTML = 'Il più grande divisiore primo di <span>'+number+"</span> è <span>" + maxPrime+"</span>"; 
    } 
function time(t){ 
      return console.log(Date() - t); 
     } 

- トン5秒ごとに、何かをsetInterval(Date()-t,5000)

+1

最大の素因数を取得しようとしていますか?次に、素因数を見つけたら、それを数で割ってください。 – Oriol

+0

はい、modで、if(isPrime(i)&& number%i == 0) 'を実行しましたが、クロムブラウザが常にcharshesするので、括弧はJSにありますので、もっと時間を与えたいです... UPDATE:あなたが私に言いたいことを教えてください。 – Teshtek

+1

'number%i!= 0'まで、' number/= i'を意味します。 'number'がさまざまな素因数を持つならば、ループを短くします。 – Oriol

答えて

1

JavaScriptのようなマルチスレッド化されていません。つまり、setInterval()はコードn ms(あなたの例では5000)を実行しているとみなします。しかしそれは事実ではありません。インターバルが経過したときにすでにスクリプトが実行されている場合、実行されるキューにコードのビットが追加されますが、実行中のスクリプトが終了するまでそのキューからは何も実行されません。

ですから、大まかに言えば、それはなぜ機能しないのですが、何をすべきですか?問題3()が戻る前に何かが起きるようにしたいのであれば、problem3()は同期的に起こらなければなりません。

たとえば、lastOutputTime変数を作成し、現在の時刻に初期化し、forループを使用して各繰り返しで現在の時刻と格納された値を比較することができます。 5秒が経過するとコンソールに出力し、lastOutputTimeを更新します。

+0

私は完全に理解しています!とにかく、私は自分のコード関数にバグを見つけました: 'time(t){ return console.log(Date()-t); } 'Date()'の前に**新しい**を忘れていますので、 'time(t){ return console.log(new Date() - t); } '作品 – Teshtek

2

これは、ワーカーAPIの使用を検討する場合があります。ブラウザをフリーズさせる代わりに、バックグラウンドでジョブを実行させ、完了したらメインスレッドにコールバックします。

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API

+0

はい、私は一般的な解決策が必要です。私は** WebワーカーがDOMとやり取りできないことを意味します** – Teshtek

+0

これは目的にかなうものです。結果が出ると、ワーカーはメッセージをUIスレッドに返し、後者はDOMを更新します。クリックイベントを傍受するよりも複雑ではなく、スレッド間で非同期データを共有する場合に起こる混乱の多くを回避します。 –

1

あなたのアルゴリズムは、このようなものに改善する必要があります:あなたはあまりにも多くの時間を必要とするいくつかの数値の場合は

function maxPrimeFactor(number) { 
 
    if (number == 0 || !Number.isInteger(number) || 
 
     number > Number.MAX_SAFE_INTEGER) return NaN; 
 
    number = Math.abs(number); 
 
    while(number % 2 == 0) number /= 2; 
 
    for (var i = 3; i * i <= number; i += 2) { 
 
    while(number % i == 0) number /= i; 
 
    } 
 
    return number; 
 
} 
 
var number = 600851475143; 
 
console.log('maxPrimeFactor(' + number + ') == ' + maxPrimeFactor(number));

、その後、小さなチャンクにループを切断し、非同期にする。しかしsetIntervalを使用しない場合は、特にの場合はsetIntervalを長いループの中に使用しないでくださいsetIntervalは実行するタスクを毎にnミリ秒に設定します。したがって、ループで使用する場合、i回繰り返したあと、nミリ秒ごとにタスクが実行されます。 setIntervalは、タスクがnミリ秒より多くかかるとブラウザがフリーズする可能性があるため、問題があります。代わりにsetTimeoutを使用してください。

ただし、この場合、これは役に立たないでしょう。上記のアルゴリズムは、304250263527209(15桁)が素数であることをほぼ即座に検出できます。最大の安全な整数が9007199254740991(16桁)であることを考えると、どの数字にも問題がないとは思いません。

アルゴリズムに時間がかかりすぎると言うなら、それはもっと大きな数字で試している可能性があります。しかし、JS番号は64ビット浮動小数点数なので、整数は正確にNumber.MAX_SAFE_INTEGERより上に表すことはできません。とにかく間違った結果が得られるので、それを計算しようとしないでください。プロジェクトオイラー#551の場合

、力ずくのアプローチは、問題を解決するための適切な方法ではないコースのブルート力

function sumOfDigits(n) { 
 
    var sum = 0; 
 
    while(n != 0) { 
 
    sum += n % 10; 
 
    n = Math.floor(n/10); 
 
    } 
 
    return sum; 
 
} 
 
function sumDigitsSeq(n) { 
 
    return new Promise(function(resolve) { 
 
    var i = 1; 
 
    var chunkSize = 1e5; 
 
    var sum = 1; 
 
    (function chunk() { 
 
     chunkSize = Math.min(chunkSize, n-i); 
 
     for (var j=0; j<chunkSize; ++j, ++i) { 
 
     sum += sumOfDigits(sum); 
 
     } 
 
     if (i >= n) return resolve(sum); 
 
     console.log('Please wait. sumDigitsSeq(' + i + ') == ' + sum); 
 
     setTimeout(chunk, 60); 
 
    })(); 
 
    }); 
 
} 
 
var number = 1e6; 
 
sumDigitsSeq(number).then(function(result) { 
 
    console.log('Done! sumDigitsSeq(' + number + ') == ' + result); 
 
});

あろう。

+0

これはアルゴリズムの本当に良い解決策ですが、どうすればこの[EULER PROBLEM](https://projecteuler.net/problem=551)を行うことができるのですか? 'var max = 1e +15; \t \t \t var sum =新しいBigNumber(1); { \t \t \t \t和= sum.plus(scomponi(和、0));}(; iは最大 Teshtek

+0

@Teshtekとにかく、私はあなたがこれらのオイラーの問題を解決するために強引な力を使用するはずだとは思わない。おそらく数式を使って簡単な数式を見つけることになっています。 – Oriol

+0

はい、数学のトリックはありますが、長いループや大きなタスクを処理する方法を学びたいだけです。時間がかかるのは、jsです – Teshtek

関連する問題