2010-10-26 8 views
2

J'ai posé une question il y a quelques semaines sur l'utilisation de setTimeout pour une fonction factorielle, mais c'était malheureusement avec un compte non enregistré et je n'ai jamais eu de réponse complète.Comment écrire une fonction factorielle en Javascript en utilisant setTimeout ou setInterval

Mon problème principal est que je voudrais écrire une fonction qui calcule la factorielle d'un nombre mais utilise les commandes setTimeout ou setInterval. L'impulsion derrière ceci est de réinitialiser un compteur que l'IE utilise afin d'éviter un avertissement de script de longue durée. À l'heure actuelle, la fonction factoriel j'est:

Dans mon autre post
function factorial(n) { 
    return 0 === n || 1 === n ? 1 : n * factorial(n - 1) 
} 

, jsumners a eu la gentillesse de me fournir le code qui a essayé d'utiliser setTimeout périodiquement lors du calcul factoriel:

function factorial(x) { 
executions++; 
    if (x > 1) { 
     if (executions % 20 === 0) { 
      return (function() { 
       var y = x; 
       setTimeout(function(y) { return y*factorial(y-1); }, 1); 
      }); 
     } else { 
     return x*factorial(x-1); 
     } 
    } else { 
    executions = 0; 
     return 1; 
    } 
} 

Dans le Au-dessus du code, il devrait théoriquement utiliser la commande setTimeout pour effectuer la prochaine multiplication lorsque le nombre d'exécutions écoulées est un facteur de 20 (mod 20). Malheureusement, le code ne fonctionne pas, et ce qui se passe est que si vous essayez de calculer la factorielle d'un nombre supérieur à 20, alors le résultat est NaN. Si le nombre est inférieur à 20, alors la réponse est correcte.

Est-ce que quelqu'un connaît une solution à ceci ou un autre moyen de calculer un factoriel en utilisant les commandes setTimeout ou setInterval?

Merci!

Répondre

4

C'est parce que vous spécifiez y comme paramètre qui est undefined lorsqu'il est exécuté parce qu'il est pas passé, vous pouvez y remédier par le changement ceci:

setTimeout(function(y) { return y*factorial(y-1); }, 1); 

à ceci:

setTimeout(function() { return y*factorial(y-1); }, 1); 

Cependant, ce sera toujours NaN car ici:

 return (function() { 
      var y = x; 
      setTimeout(function() { return y*factorial(y-1); }, 1); 
     }); 

Vous renvoyez toujours une fonction, pas un nombre qui peut être multiplié, de sorte que vous ne pouvez toujours pas utiliser un de cette manière. Vous pouvez passer un rappel qui s'exécute lorsque tout est fait, mais vous ne pouvez pas le faire recurse et revenir à un appelant comme celui-ci.

+0

Merci pour briser le code pour moi et me faire savoir quel était le problème. Cela dit, je devrais dire que je suis un amateur de Javascript, donc je ne sais pas trop comment mettre en place un rappel comme vous l'avez suggéré. Est-ce que je me débarrasse de la syntaxe 'return' et que j'ai simplement la commande setTimeout, et une fois que le multiplicateur descend à 1, j'appelle un callback qui renvoie la réponse? Merci encore pour votre aide. – Josiah

0

Le factoriel style de rappel à chaque étape récurrente prévue avec setTimeout est:

// private helper function (recurrency with accumulation) 
function _factorial(acc, n, callback){ 
    if(n==0){ 
    callback(acc); 
    }else{ 
    var callback_wrapper = function(result){ 
     callback(result); 
    }; 
    setTimeout(function(){_factorial(acc * n, n-1, callback_wrapper)}, 10); 
    } 
} 

// public function 
function factorial(n, callback){ 
    _factorial(1, n, callback); 
} 

// usage example 
factorial(10, function(result){console.log(result)}); 

- Cheers, Lambder

http://lambder.com/

http://vanadiumJS.com/

Questions connexes