Factoriel - Algo - Programmation
Marsh Posté le 16-11-2005 à 11:45:25
Pose le calcul de la factorielle de manière simple, et regarde la répétition.
Marsh Posté le 16-11-2005 à 11:48:14
Excusez moi j'ai posté trop vite:
J'ai trouvé la réponse:
[fixed]
fact = 1
Pour i de 1 à x
fact = fact * i
Fin Pour
Marsh Posté le 20-11-2005 à 12:35:27
factoriel(n)
if n=1
return 1
else
return n * factoriel(n-1)
end if
end function
Marsh Posté le 20-11-2005 à 16:18:14
ReplyMarsh Posté le 20-11-2005 à 16:21:34
betsamee a écrit : en effet la recursion c'est plus joli |
Ouais, mais bon, dans la pratique, c'est malheureusement à éviter.
Marsh Posté le 20-11-2005 à 16:29:59
sircam a écrit : Ouais, mais bon, dans la pratique, c'est malheureusement à éviter. |
question reelement innocente (je me rappeles plus trop de mes cours de C++ ca fait un bail) :
pourquoi la recursion serait a eviter dans un cas pareil ? (est ce pour eviter de tomber dans des appels infinis si la fonction est mal codee?)
pour calculer une factorielle ca semble tout a fait etre le cas typique de recursion
Marsh Posté le 20-11-2005 à 16:37:44
c'est que la récursion empile des appels de fonctions sur la pile d'appel et que passé un certain niveau de récursion imbriqué le programme crash.
Mais il faudrait que le nombre soit très grand pour faire suffisament d'appels récursifs imbriqués pour que Factoriel crash.
D'autre part, souvent il y a un coût à chaque appel de méthode, et par conséquent, la première méthode serait peut-être plus efficace (tout dépend aussi des optimisations du compilateur / jvm)
Je te répond en général pour un langage comme Java ou C++. Je ne suis pas sur de la limite dans un langage comme LISP .
Marsh Posté le 20-11-2005 à 16:42:30
Pfv3 a écrit : c'est que la récursion empile des appels de fonctions sur la pile d'appel et que passé un certain niveau de récursion imbriqué le programme crash. |
ok
Marsh Posté le 20-11-2005 à 17:01:15
Pfv3 a écrit : c'est que la récursion empile des appels de fonctions sur la pile d'appel et que passé un certain niveau de récursion imbriqué le programme crash. |
Et plus le langage est de haut niveau plus ça coûte cher
En Java, ça coûte déjà bonbon, mais dans des langages comme Python ou Ruby, un appel de fonction coûte extrèmement cher.
Demo:
>>> def fact1(n): |
timeit.Timer permet (en python) de timer des mini bouts de code, ici on calcule factoriel(20) avec chacune des deux méthodes.
timeit.Timer.repeat(x,y) permet de lancer x "runs" de y exécutions du code du Timer associé, et renvoie le temps pour chacun de ces runs (la somme des temps des y exécutions).
Donc ici on fait 3 runs, chaque run comptant un million d'exécution de factoriel(20).
Et la différence en temps d'exécution (le résultat est en secondes) est d'un rapport 2
Marsh Posté le 20-11-2005 à 17:39:29
De plus, indépendemment de la question de pile d'appel, certains traitements récursifs sont coûteux en soi, p.e. les manip de chaînes (cette rq ne s'applique pas à factoriel).
Si tu fais un traitement récursif sur une chaîne, et que appelles ta fn récursivement avec des bouts de sous-chaîne, ça va te coûter un max et ta pile d'appel deviendra un problème secondaire face aux affres de la conso mémoire que tu vas te taper.
Marsh Posté le 20-11-2005 à 17:58:04
Tu veux parler des chaînes locales aux fonctions ?
Tu m'arrêtes si je dis une co****rie, mais ta pile d'appel, c'est bien la pile d'exécution, non, donc les chaînes locales en augmentent aussi la taille ?
Marsh Posté le 20-11-2005 à 18:22:53
Ouaip, c'est plus correct et plus précis. Je tentais de faire une distinction entre le coût de l'appel récursif sensu stricto et les coûts connexes. Ces derniers peuvent devenir prohibitifs dans certains cas.
Marsh Posté le 20-11-2005 à 18:52:41
Masklinn >> flûte, python c'est pourri alors !
Je croyais qu'il héritait d'un noyau en C où justement les appels de fonctions sont peu cher.
Bon, heureusement que pour ce que j'en fait avec j'ai pas besoin qu'il soit trop véloce mais là je suis déçu.
Marsh Posté le 20-11-2005 à 19:03:59
pains-aux-raisins a écrit : Masklinn >> flûte, python c'est pourri alors ! |
Citation : Je croyais qu'il héritait d'un noyau en C où justement les appels de fonctions sont peu cher. |
T'as fumé?
Et en Python, une fonction est un objet de première classe, je ne vois même pas comment tu pourrais utiliser directement des fonctions C
Citation : Bon, heureusement que pour ce que j'en fait avec j'ai pas besoin qu'il soit trop véloce mais là je suis déçu. |
Marsh Posté le 20-11-2005 à 20:23:58
ouaip, ben vu la tendance actuelle, bientot les interpréteurs devront génèrer mille instructions machine pour additionner 1 et 2...
c'est le progrès quoi
Marsh Posté le 20-11-2005 à 21:08:49
pains-aux-raisins a écrit : ouaip, ben vu la tendance actuelle, bientot les interpréteurs devront génèrer mille instructions machine pour additionner 1 et 2... |
J'crois que t'as un peu de mal avec le concept de niveaux de langages, et du choix à faire entre simplicité du code/vitesse de développement et vitesse d'exécution/conso mémoire
Marsh Posté le 20-11-2005 à 21:16:15
masklinn a écrit : J'crois que t'as un peu de mal avec le concept de niveaux de langages, et du choix à faire entre simplicité du code/vitesse de développement et vitesse d'exécution/conso mémoire |
Tu m'a pas pris aux sérieux j'espère ?
Je pense savoir faire la différence entre les différents niveaux de langage au moins aussi bien que toi.
Si je préconise dans ma boite du python, du .NET et autre technique RAD c'est que j'ai également posé la problèmatique
Marsh Posté le 21-11-2005 à 01:53:15
Ben j'ai fait un petit test en OCaml
Voici le source:
Code :
|
Et voilà ce que ca donne:
# - : string = "Le résultat comporte: 19 chiffres"
# - : string = "Temps pour fact de 20 en récursif: 0. sec"
# - : string = "Temps pour fact de 20 en impératif: 0. sec"
# - : string = "Le résultat comporte: 375 chiffres"
# - : string = "Temps pour fact de 200 en récursif: 0.0100000000002 sec"
# - : string = "Temps pour fact de 200 en impératif: 0. sec"
# - : string = "Le résultat comporte: 5736 chiffres"
# - : string = "Temps pour fact de 2000 en récursif: 0.09 sec"
# - : string = "Temps pour fact de 2000 en impératif: 0.08 sec"
# - : string = "Le résultat comporte: 77338 chiffres"
# - : string = "Temps pour fact de 20000 en récursif: 7.31 sec"
# - : string = "Temps pour fact de 20000 en impératif: 6.539 sec"
# - : string = "Le résultat comporte: 213237 chiffres"
# - : string = "Temps pour fact de 50000 en récursif: 78.903 sec"
# - : string = "Temps pour fact de 50000 en impératif: 74.367 sec"
Bon c'est vrai que l'impératif est un poil plus rapide, mais bon c'est pas trop flagrant. Faut commencer à aller
chercher de grosse factorielle pour voir un écart se creuser.
Marsh Posté le 21-11-2005 à 06:23:13
En C avec libgmp sous linux, ça donne (je viens de découvrir libgmp, donc on peut surement faire mieux) :
Code :
|
Ce qui donne (je ne colle pas les factorielles ici) :
$ ./fact 50000 r |
On voit que le récursif est de plus en plus à la traîne quand les nombres deviennent grands : seulement 5% plus lent pour 50000, mais 40% plus lent pour 123456. Pour 500000, je segfault en récursif par manque de pile... Il faudrait jouer avec les options de ld pour allouer une stack plus grande.
Marsh Posté le 10-12-2005 à 11:11:24
Histoire de completer le sujet et confirmer que le BASIC s'il est facile à apprendre, est tout sauf rapide.
Code :
|
resultat pour 20000!
125 sec
longueur : 77338 chiffres
Pour 50000! il tourne encore .....
@++
Marsh Posté le 10-12-2005 à 12:20:06
et voila le resultat !
880 sec
longueur : 213237 chiffres
no comment please !
Marsh Posté le 07-10-2011 à 22:30:45
Bonjour à tous.
Dans le cadre d'un exercice de programmation basique, nous cherchons à mettre un place un programme permettant de calculer une suite de la forme :
S=x+(x^3/3!)+(x^5/5!)....
Je cherche donc par conséquent à déterminer programmer la factorielle de la forme suivante : (2i+1)!
J'ai donc fais ceci (langage fortran95)
fact=1
DO i=2*i+1,N
fact=fact*i
END DO
De manière à essayer d'avoir uniquement les factorielles impaires. Mais je ne suis pas convaincu du résultat, puisque quand N est pair, il me donne quand même une factorielle paire ...
A l'avance, je vous remercie.
Marsh Posté le 07-10-2011 à 23:12:50
Je ne connais pas trop ce langage mais je ne suis pas sur que la suite des "i" soit bien la bonne.
Plutôt :
fact=1
DO i=i+1,N
fact=fact*(2*i+1)
END DO
Marsh Posté le 08-10-2011 à 13:25:02
Merci de ta réponse.
Je viens de le programmer, cela ne semble pas marcher non plus.
Marsh Posté le 08-10-2011 à 14:04:14
Bon déjà je comprends pas trop ce que vous faites:
pour calculer la factorielle de 2N+1, on fait:
fact = 1
DO i = 1, 2*N+1
fact = fact*i
END DO
Parce que dans une factorielle, il y a tous les facteurs, qu'ils soient impairs ou pair.
Et d'autre part, si en Fortran, on veut faire une boucle sur les nombres impairs inférieurs ou égal à N, on fait
DO i = 1, N, 2
...
END DO
A+,
Marsh Posté le 08-10-2011 à 20:00:54
Revoici Jovalise...
Décidément les résultat sont surprenant, Gilou !
Voilà le mon code avec Ada
Code :
|
Et voici les résultat pour X alant de 1 à 9
S= 1 |
Marsh Posté le 16-11-2005 à 11:42:25
Salut
Je voudrais connaitre l'algo pour faire un factoriel...
Merci