7
votes

Comment faites-vous une double factorielle en python?

J'ai été cru sur cette question pendant une période très longue. J'ai réussi à faire un seul facteur factoriel récursif.

def factorial(n):
     if n == 0:
         return 1
     else:
         return n * factorial(n-1)


2 commentaires

Regardez ce qui change entre les deux: le n-1 devient n-2 et le numéro final (case bases) passe de 0 à l'une de 2 ou 1.


Quand j'ai vu cette question, j'ai fait une double prise.


10 Réponses :


0
votes
def doublefactorial(n):
     if n <= 0:
         return 1
     else:
         return n * doublefactorial(n-2)
That should do it. Unless I'm misunderstanding

1 commentaires

Pourquoi retournez-vous 2 pour n == 0? Il devrait être 1, il suffit d'utiliser si n <= 1: retour 1 , bien qu'il soit vraiment doit être si n <0: crier fort si n in (0, 1): retour 1 < / code>



4
votes

n'est-ce pas identique à la même manière que la factorielle avec une condition de fin différente et un paramètre différent de l'appel de récursivité? xxx

si n est même, Ensuite, il arrête quand n == 0 . Si n est impair, il s'arrêtera lorsque n == -1 .


2 commentaires

Vous voudrez appeler Difficile dans l'appel récursif. Fait la même erreur.


Vous pouvez arrêter à 1 au lieu de -1. Je sais, amélioration minimale, mais toujours. :)



19
votes
from functools import reduce # only in Python 3

reduce(int.__mul__, range(n, 0, -2))

5 commentaires

Attendez, cela se fait effectivement suscité? Au moins, utilisez opérateur.mul (un peu plus propre, car vous ne tapez pas de soulignement, et est "type-agnostic"). Et moi, car j'espère que la version explicitement itérative de toute façon, si je devais éviter les débordements de la pile (et mentionné ci-dessous, c'est pas le point de la plupart des missions factorielles).


Le point de toute fonction factorielle est également d'enseigner à la récursivité des personnes, et non d'être efficace. Et vous trouverez que Xrange est encore plus efficace. ;)


@delnan: Depuis Plage uniquement des rendements INT , à l'aide de int .__ mul __ est d'accord (et ne doit pas avoir à faire une autre importation). @Lennart Regèbre: True. Cependant, j'ai écrit ce code dans Python 3. En ce qui concerne l'utilisation de la récursion, vous ne pensez pas que le réduire peut être considéré comme une fonction de récursivité? Comprendre cela pourrait être une aide.


réduire (long .__ mul __, plage (n, 0, -2), 1L) évite le problème lorsque le produit devient trop grand


Ceci est considéré comme un python obscurci? Wow. Cela me semble assez normal, c'est juste un pli standard, tout comme j'utiliserais à Haskell ou Lisp.



0
votes
def doublefactorial(n):
     if n in (0, 1):
         return 1
     else:
         return n * doublefactorial(n-2)
should do it.

0 commentaires

0
votes

J'espère que je le comprends correctement, mais cela fonctionnera-t-il xxx


2 commentaires

Pas assez. Vous devez ajuster le boîtier de base, sinon il ne se termine pas pour des nombres impairs.


Vous auriez besoin de vous arrêter à moins de 0 sinon une valeur étrange entrera dans une boucle infinie (ou finalement frapper un flux d'empilement)



0
votes
def double_fact(number):
    if number==0 or number==1:
        return 1
    else:
        return number*double_fact(number-2)
I think this should work for you.

0 commentaires

0
votes

Réduire (Lambda x, Y: Y * x, plage (n, 1, -2))

qui est fondamentalement identique à la simple version itérative: < PRE> XXX

Évidemment, vous pouvez également le faire de manière récursive, mais quel est le point? Ce type d'exemple mis en œuvre à l'aide de la récursivité est bien lorsque vous utilisez toutes les langues récursives, mais avec une langue impérative, il fait toujours des outils simples, tels que la récursivité plus complexe que nécessaire, tandis que la récursivité peut être un véritable simplificateur lorsqu'il s'agit de structures fondamentalement récursives comme des arbres.


0 commentaires

1
votes

Ma version de la solution récursive, dans une ligne: xxx pré>

Cependant, il est également intéressant de noter que le double factoriel peut être exprimé en termes de factorielle "normale". Pour les nombres impairs, p>

n !! = (2 * k)! / (2 ** k * k!) P>

où k = (n + 1) / 2. Pour les arguments n = 2k, bien que cela ne soit pas cohérent avec une généralisation à des arguments complexes, l'expression est plus simple, p>

n !! = (2k) !! = 2 * k * k!. P>

Tout cela signifie que vous pouvez écrire du code à l'aide de la fonction factorielle de la bibliothèque de mathématiques standard, qui est toujours agréable: P>

import math
fact = math.factorial
def dfact(n):
  if n % 2 == 1:
    k = (n+1)/2
    return fact(2*k) / (2**k * fact(k))
  else:
    return 2**k * fact(k)


0 commentaires

3
votes

Le problème ici est que le double factorial est défini pour les nombres réels négatifs (-1) !! = 1, (-3) !! = -1 (même des entiers négatifs (tels -2, -4, ...) devraient avoir une solution comme +/- INF) afin ... quelque chose sent mal dans toutes les solutions pour des nombres négatifs. Si on veut définir la double factorielle pour Al Reals, ces solutions ne fonctionnent pas. La solution consiste à définir la double factorielle à l'aide de la fonction gamma. xxx

Ça fonctionne! : D


0 commentaires

1
votes

Démarrage python 3.8 , nous pouvons utiliser le prod fonction de la math module qui calcule le produit de tous les éléments d'un iérhable, lequel dans notre cas est plage (n, 0, -2) : xxx

Notez que cela gère également le cas n = 0 auquel le résultat est 1 .


0 commentaires