Je résolvez un problème de trois manières différentes, deux sont récursifs et je les mémoise moi-même . L'autre n'est pas récursif mais utilise maths.factorial. J'ai besoin de savoir si j'ai besoin d'ajouter une mémoire explicite à elle. P>
Merci. P>
4 Réponses :
Recherchez MATH_Factorial sur ce lien et vous trouverez sa mise en œuvre en Python: P>
http://svn.python.org/ Affichage / Python / Trunk / Modules / MathModule.c? Vue = marquage p>
P.s. Ceci est pour Python2.6 P>
Merci Asterisk, (êtes-vous une Gaule par hasard)?
Python's Math.Factorial n'est pas mémo, il est simple de multiplier les valeurs de 1 à votre ARG. Si vous avez besoin de mémoisation, vous devez le faire explicitement.
Voici un moyen simple de mémoiser à l'aide de la méthode Dictionnaire SetDefault. P>
import math
cache = {}
def myfact(x):
return cache.setdefault(x,math.factorial(x))
print myfact(10000)
print myfact(10000)
Merci Sentihil. J'ai pu confirmer cela de la source.
@ Paddy3118 - Ajout d'un exemple simple. Il n'utilise pas de décorateur, mais utilise simplement la méthode SetDefault de Dictionary qui peut être utile à de telles fins.
Merci encore @venenthil. J'utilise une version moins flexible du code de ici , que je peux utiliser pour décorer trois Fonctions .
Cela n'atteint aucun avantage de performance. SETDEFAULT CODE>, comme toutes les méthodes Python, évalue toujours tous ses arguments - il ne shortcuit pas lorsque la clé est déjà présente dans le dictionnaire. Au lieu de cela, vous devez soit utiliser résultat = cache.get (x) code> et tester pour aucun ou si x dans cache: ... code> J'ai fait cette même erreur moi-même . cache.get (x, math.factorial (x)) code> n'est pas meilleur non plus.
Je pense que @Peter doit avoir raison. Malheureusement, je ne peux pas changer mon uppote. :-) Pour une autre façon de mémoiser une fonction, voir Python-Course.eu/python3_memoize.php < / a>
@Peterdeglopper Vous avez raison. En outre, définir la factorielle commémorée de cette façon n'atteint pas beaucoup. Si vous appelez MyFact (1000), le résultat est mémoisé. Mais si vous appelez MyFact (999) peu de temps après cela, le résultat est calculé ne tenant pas en compte que MyFact (1000) avait déjà calculé MyFact (999). Le seul moyen de réaliser une bonne amélioration de la performance est de redéfinir l'ex-novo une fonction factorielle récursive mémo.
(continuant de mon dernier commentaire) en train de la mettre en œuvre de manière récursive peut bientôt conduire à une profondeur de récursivité excessive. Mieux de le mettre en œuvre de manière itérative.
MATHON'S MATH.Factorial n'est pas mémoré.
Je vais vous guider à travers des exemples d'essais et d'erreurs pour savoir pourquoi obtenir une fonction motivée vraiment mémo et optique que vous devez redéfinir l'ex-novo prise en compte Quelques choses. P>
L'autre réponse n'est pas correcte. Ici, p> la ligne p> calcule les deux Vous pouvez penser à faire quelque chose comme ceci: p> mais En fait, cela est faux aussi bien. Oui, vous évitez de calculer à nouveau la factorielle d'un même Il est naturel Ensuite, écrire quelque chose comme ceci: p> Cela va fonctionner. Malheureusement, il atteint bientôt la profondeur de récursion maximale. P> Alors comment la mettre en œuvre? P> Voici un exemple de factorielle vraiment mémodiale, qui tire parti de la facture qui fonctionne et ne consomme pas tous La pile avec des appels récursifs: p> J'espère que vous trouverez cela utile. p> EDIT: FORT> P> Tout comme une note, un moyen d'atteindre cette même optimisation ayant en même temps la concision et l'élégance de la récursivité consisteraient à redéfinir la fonction sous la forme d'un la fonction de la queue-récursive . p> x code> et maths. factorielle (x) code> à chaque fois et que vous ne gagnez donc aucune amélioration de la performance. P> x code> mais pense, par exemple, si vous allez calculer myfact (1000) code> et peu de temps après que myfact (999) code>. Les deux sont calculés complètement, ne prenant aucun avantage du fait que MyFact (1000) compose automatiquement MyFact (999) code>. P> RuntimeError: maximum recursion depth exceeded
Vous voulez omettre la récursion et utiliser une boucle.
Pouvez-vous reformuler cela, s'il vous plaît? Demandez-vous s'il est possible de faire de même avec une définition récursive de la fonction? Si c'est la question, il serait possible en redéfinissant la fonction de manière récursive de la queue tant que l'interprète que vous utilisez soutient cela. La fonction de la queue récursive peut être en effet reconnue par le compilateur / interprète et être traduite / optimisée à un algorithme itératif. Malheureusement, comme vous pouvez le constater à partir de mon dernier édition Standard Python Interprète 2.7.3 ne semble pas supporter cela.
Il existe de nombreux décorateurs qui effectuent une pseudo-optimisation des appels quotidiens en python, ils empêchent la pile d'appels de débordement.
@Elikorvigo intéressant. Pourriez-vous fournir plus d'informations à ce sujet?
@Domenicodefelice Bien sûr, je préfère personnellement le recur.Tcodécorateur de l'emballage FN pour plusieurs raisons, bien que certaines limitations (à savoir, votre fonction doit être modifiée de manière particulière). J'ai vu de nombreux décorateurs qui fonctionnent avec presque toutes les fonctions. Celui-ci est un exemple (pourrait être délicat avec imbriqué Fonctions), et il existe de nombreux autres exemples donnés dans les commentaires.
@Domenicodefelice Mon plaisir. J'ai posté une autre implémentation d'une fonction factorielle mémo. Vous voudrez peut-être regarder.
Je suis en retard à la fête, mais voici mon 2C sur la mise en œuvre d'une fonction factorielle mémo indiquée efficace en Python. Cette approche est plus efficace car elle s'appuie sur une structure semblable à une matrice (c'est-à-dire la liste code>) plutôt qu'un conteneur haché (c'est dict code>). Aucune récursion impliquée (ne vous évacue pas de la fonction de fonction Python-Call-orthographe) et aucune lente à boucles lentes impliquées. Et il est (sans doute) fonctionnellement pur car il n'y a pas d'effets secondaires extérieurs impliqués (c'est-à-dire qu'il ne modifie pas une variable globale). Il met en cache tous les factoriels intermédiaires, d'où si vous avez déjà calculé factorial (n) code>, il vous faudra O (1) pour calculer factorielle (m) code> pour n'importe quel 0 < = M <= N et O (mn) pour tout M> n.
Belle solution. Les seules choses que je n'aime pas sont: 1) le ou cache code> s'appuyant sur la connaissance que Ajoutez code> renvoie Aucun code> (quelque chose de plus explicite serait Mieux et plus clair pour comprendre), 2) Je ne sais pas ce que vous voulez dire avec "lent-boucles", mais que, si nous ne nous soucions que de la performance, je ne pense pas que réduire code> est plus rapide: Il fait un appel de fonction à la Lambda à chaque étape (à moins que l'interprète n'offre une optimisation qui définit le code Lambda)
Vous pouvez le vérifier vous-même en exécutant
math.factorial code> deux fois avec un numéro suffisamment grand, par ex. n = 50000Si vous êtes intéressé par une implémentation différente de factorielle à Python, c'est un bel article: metaleks.net/programmer/the-evolution-fof-a-python-programme r