2016-10-08 3 views
-1

Ich schreibe ein Programm Primzahlen in JavaScript zu generieren. Das Problem ist, dass das Verhalten des Programms sehr seltsam ist, es scheint, dass die Funktionen nicht in der Reihenfolge ausgeführt werden, die es daran hindert, ordnungsgemäß ausgeführt zu werden. Hier ist mein Code:Funktionen unerwartetes Verhalten in JavaScript geben

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
\t <title>Generate Some Primes!</title> 
 
</head> 
 

 
<body> 
 
\t <h1>Let's Generate Some Primes!!!</h1> 
 
\t <form id="userInput"> 
 
\t \t <ul> 
 
\t \t \t <li> 
 
\t \t \t \t <label>Lower Bound (inclusive):</label> 
 
\t \t \t \t <input type="number" id="lower"> 
 
\t \t \t </li> 
 
\t \t \t <li> 
 
\t \t \t \t <label>Upper Bound (exclusive):</label> 
 
\t \t \t \t <input type="number" id="upper"> 
 
\t \t \t </li> 
 
\t \t \t <li> 
 
\t \t \t \t <input type="submit" value="Generate!"> 
 
\t \t \t </li> 
 
\t \t </ul> 
 
\t </form> 
 
\t <p id="messageBox"></p> 
 
\t <ul id="primes"></ul> 
 
\t <script> 
 
\t var primesList = document.getElementById("primes"); 
 
\t var lower; 
 
\t var upper; 
 
\t var NOT_STARTED = "Generating ..."; 
 
\t var DONE = "Done!"; 
 
\t window.onload = function() { 
 
\t \t userInput.onsubmit = function(e) { 
 
\t \t \t e.preventDefault(); 
 
\t \t \t writeMessage(NOT_STARTED); 
 
\t \t \t if (checkInput()) { 
 
\t \t \t \t checkNumbers(); 
 
\t \t \t \t writeMessage(DONE); 
 
\t \t \t } 
 
\t \t } 
 
\t } 
 

 
\t function checkInput() { 
 
\t \t initializeBounds(); 
 
\t \t if (lower >= upper) { 
 
\t \t \t writeMessage("Lower bound must be less than upper bound."); 
 
\t \t \t return false; 
 
\t \t } 
 
\t \t return true; 
 
\t } 
 

 
\t function initializeBounds() { 
 
\t \t lower = Math.round(document.getElementById("lower").value); 
 
\t \t upper = Math.round(document.getElementById("upper").value); 
 
\t \t primesList.innerHTML = ""; 
 
\t } 
 

 
\t function checkNumbers() { 
 
\t \t for (var i = lower; i < upper; i++) { 
 
\t \t \t if (isPrime(i)) 
 
\t \t \t \t writePrime(i); 
 
\t \t } 
 
\t } 
 

 
\t function writePrime(p) { 
 
\t \t primesList.innerHTML += "<li>" + p + "</li>"; 
 
\t } 
 

 
\t function writeMessage(message) { 
 
\t \t var messageBox = document.getElementById("messageBox"); 
 
\t \t messageBox.innerHTML = message; 
 
\t } 
 

 
\t function isPrime(p) { 
 
\t \t if (p < 2) 
 
\t \t \t return false; 
 
\t \t for (var b = p - 1; b > 1; b--) 
 
\t \t \t if (GCD(p, b) > 1) 
 
\t \t \t \t return false; 
 
\t \t return true; 
 
\t } 
 

 
\t function GCD(a, b) { 
 
\t \t if (b == 0) 
 
\t \t \t return a; 
 
\t \t else 
 
\t \t \t return GCD(b, a % b); 
 
\t } 
 
\t </script> 
 
</body> 
 

 
</html>

Das sind meine Probleme:

  1. Wenn die untere Grenze liegt in der Nähe der oberen Grenze, und sie sind beide relativ große Zahl, keine Ausgabe erzeugt (zum Beispiel versuchen, 900 als die untere Grenze und 1000 als die obere Grenze der Eingabe), obwohl ich weiß, sicher Primzahlen existieren, und dass m y Methode zum Generieren funktioniert.

  2. die Primzahlen sollte auf dem Bildschirm angezeigt werden, da sie, und nicht am Ende erzeugt werden, wenn sie alle geschaffen. Wenn Sie den Eingang 0 als untere Grenze und 10000 als die obere Grenze man deutlich das Problem sehen (Ich schlage vor, das Snippet Vollbild ausgeführt wird und gerade die Scrollbar Größe).

  3. Dies bezieht sich auf Nummer 2. Die Nachricht Generating ... wird nie angezeigt, nur Done.

EDIT: Ich habe einige Änderungen an dem Code, der das erste Problem gelöst.

+0

Sie bitte Ihre Frage bearbeiten, "screwy Javascript Verhalten" ist keine Frage. – Soviut

+0

@Soviut ist das besser? – theEpsilon

+0

Woah, was ist los mit den Downvotes? Ich ging in einer Stunde von +2 auf -1. Bitte erklären Sie sich selbst. – theEpsilon

Antwort

1

Ich würde vorschlagen, Promises zu verwenden, um das Blockierungsverhalten der for-Schleife zu unterbrechen und dem Browser/UI genügend Zeit zu geben, die Ergebnisse zu rendern.

<body> 
 
    <h1>Let's Generate Some Primes!!!</h1> 
 
    <form id="userInput"> 
 
     <ul> 
 
     <li> 
 
      <label>Lower Bound (inclusive):</label> 
 
      <input type="number" id="lower"> 
 
     </li> 
 
     <li> 
 
      <label>Upper Bound (exclusive):</label> 
 
      <input type="number" id="upper"> 
 
     </li> 
 
     <li> 
 
      <input type="submit" value="Generate!"> 
 
     </li> 
 
     </ul> 
 
    </form> 
 
    <p id="messageBox"></p> 
 
    <ul id="primes"></ul> 
 
    
 
    <script> 
 
    var primesList = document.getElementById("primes"); 
 
    var lower; 
 
    var upper; 
 
    var NOT_STARTED = "Generating ..."; 
 
    var DONE = "Done!"; 
 
    window.onload = function() { 
 
     userInput.onsubmit = function(e) { 
 
     e.preventDefault(); 
 
     writeMessage(NOT_STARTED); 
 
     if (checkInput()) { 
 
      checkNumbers() 
 
       .then(function() { 
 
        writeMessage(DONE); 
 
       }) 
 
     } 
 
     } 
 
    } 
 

 
    function checkInput() { 
 
     initializeBounds(); 
 
     if (lower >= upper) { 
 
     writeMessage("Lower bound must be less than upper bound."); 
 
     return false; 
 
     } 
 
     return true; 
 
    } 
 

 
    function initializeBounds() { 
 
     lower = Math.round(document.getElementById("lower").value); 
 
     upper = Math.round(document.getElementById("upper").value); 
 
     primesList.innerHTML = ""; 
 
    } 
 

 
    function checkNumbers() { 
 
     var promise = Promise.resolve(); 
 
     for (var i = lower; i < upper; i++) { 
 
     (function(i) { 
 
      promise = promise.then(function() { 
 
       if (isPrime(i)) 
 
        return writePrime(i); 
 
      }); 
 
     })(i); 
 
     } 
 
     return promise; 
 
    } 
 

 
    function writePrime(p) { 
 
     return new Promise(function(resolve, reject) { 
 
     primesList.innerHTML += "<li>" + p + "</li>"; 
 
     writeMessage("Generating ..." + Math.round(100 * p/(upper - lower)) + "%"); 
 
     setTimeout(function() { 
 
      resolve(); 
 
     }, 0); 
 
     }); 
 
    } 
 

 
    function writeMessage(message) { 
 
     var messageBox = document.getElementById("messageBox"); 
 
     messageBox.innerHTML = message; 
 
    } 
 

 
    function isPrime(p) { 
 
     if (p < 2) 
 
     return false; 
 
     for (var b = p - 1; b > 1; b--) 
 
     if (GCD(p, b) > 1) 
 
      return false; 
 
     return true; 
 
    } 
 

 
    function GCD(a, b) { 
 
     if (b == 0) 
 
     return a; 
 
     else 
 
     return GCD(b, a % b); 
 
    } 
 
    </script> 
 
</body>

Externer Link zu jsFiddle.

+0

sieht definitiv vielversprechend aus. Ich werde fortfahren zu testen – theEpsilon

+0

Große Antwort! Ich werde akzeptieren, sobald es meine Bearbeitungen hat – theEpsilon

+0

Bearbeiten akzeptiert, auf jeden Fall besser. –

0

: Verwenden Sie parseInt(), um die Eingabe (Zeichenfolge) in eine Zahl zu konvertieren.

2, 3: Die for Schleife blockiert den Fenster-Thread, deshalb sehen Sie nicht die Schritt-für-Schritt-Ergebnisse; Das DOM wird erst aktualisiert, wenn der Code abgeschlossen ist. Die Nachricht wird tatsächlich festgelegt, aber Sie können sie nicht sehen, da der Prozess blockiert ist.

Ich habe auf dem Snippet bearbeitet, die setTimeout()-Funktion, die einige Zeit, bevor Anrufe warten.

<!DOCTYPE html> 
 
    <html> 
 

 
    <head> 
 
     <title>Generate Some Primes!</title> 
 
    </head> 
 

 
    <body> 
 
     <h1>Let's Generate Some Primes!!!</h1> 
 
     <form id="userInput"> 
 
      <ul> 
 
       <li> 
 
        <label>Lower Bound (inclusive):</label> 
 
        <input type="number" id="lower"> 
 
       </li> 
 
       <li> 
 
        <label>Upper Bound (exclusive):</label> 
 
        <input type="number" id="upper"> 
 
       </li> 
 
       <li> 
 
        <input type="submit" value="Generate!"> 
 
       </li> 
 
      </ul> 
 
     </form> 
 
     <p id="progress"></p> 
 
     <ul id="primes"></ul> 
 

 
     <script> 
 
     var primesList = document.getElementById("primes"); 
 
     var lower; 
 
     var upper; 
 
     var NOT_STARTED = false; 
 
     var DONE = true; 
 
     window.onload = function() { 
 
      userInput.onsubmit = function(e) { 
 
       e.preventDefault(); 
 

 
       /* 3: let's give some time for message */ 
 
       writeProgressMessage(NOT_STARTED); 
 
       initializeBounds(); 
 

 
       window.setTimeout(function() { 
 
        checkNumbers(lower, upper); 
 
       }, 1000); // waiting for 1s to start 
 
      } 
 
     } 
 

 
     function initializeBounds() { 
 
      /* correctly convert the input's for numbers, using parseInt */ 
 
      lower = parseInt(document.getElementById("lower").value, 10); 
 
      upper = parseInt(document.getElementById("upper").value, 10); 
 
      primesList.innerHTML = ""; 
 
     } 
 

 
     function checkNumbers(current, upper) { 
 
      if (isPrime(current)) 
 
       writePrime(current); 
 

 
      /* not yet finished */ 
 
      if (current != upper) { 
 
       setTimeout(function() { 
 
        checkNumbers(current+1, upper); 
 
       }, 100); // wait 100ms for the next check 
 
      } 
 
     } 
 

 
     function writePrime(p) { 
 
      primesList.innerHTML += "<li>" + p + "</li>"; 
 
     } 
 

 
     function writeProgressMessage(done) { 
 
      var progress = document.getElementById("progress"); 
 
      if (!done) 
 
       progress.innerHTML = "Generating ..."; 
 
      else 
 
       progress.innerHTML = "Done!"; 
 
     } 
 

 
     function isPrime(p) { 
 
      if (p < 2 || !Number.isInteger(p)) 
 
       return false; 
 
      for (var b = p - 1; b > 1; b--) 
 
       if (GCD(p, b) > 1) 
 
        return false; 
 
      return true; 
 
     } 
 

 
     function GCD(a, b) { 
 
      if (b == 0) 
 
       return a; 
 
      else 
 
       return GCD(b, a % b); 
 
     } 
 
     </script> 
 
    </body> 
 

 
    </html>

+0

Gelöst # 1 und # 3. Für # 2 kann ich mir die 100ms Zeitüberschreitung nicht leisten, da ich so schnell wie möglich nachsehen muss. – theEpsilon

+1

Ich denke, Sie können stattdessen einen Web Worker verwenden oder das Zeitlimit für 0 festlegen. –

+0

Ja für Web Worker. Wenn ich du wäre, würde ich meine Antwort bearbeiten, um über sie zu sprechen – theEpsilon