Factoriel

Factoriel - Algo - Programmation

Marsh Posté le 16-11-2005 à 11:42:25    

Salut
 
Je voudrais connaitre l'algo pour faire un factoriel...
 
Merci

Reply

Marsh Posté le 16-11-2005 à 11:42:25   

Reply

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.


---------------
JE JE SUIS LIBERTINEEEEEEEEEEE JE SUIS UNE CATINNNNNNNNN §§§§§§§§
Reply

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

Reply

Marsh Posté le 20-11-2005 à 07:27:52    

disons que c'était pas compliqué!

Reply

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

Reply

Marsh Posté le 20-11-2005 à 16:18:14    

en effet la recursion c'est plus joli

Reply

Marsh 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. [:djswad]


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
Reply

Marsh Posté le 20-11-2005 à 16:29:59    

sircam a écrit :

Ouais, mais bon, dans la pratique, c'est malheureusement à éviter. [:djswad]


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

Reply

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 .

Message cité 2 fois
Message édité par Pfv3 le 20-11-2005 à 16:40:03
Reply

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.
 
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 .


ok  :jap:  

Reply

Marsh Posté le 20-11-2005 à 16:42:30   

Reply

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.
 
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)


Et plus le langage est de haut niveau plus ça coûte cher :o
 
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):
    out = 1
    for i in xrange(1, n+1):
        out*=i
    return out
 
>>> def fact2(n):
    if n == 1:
        return 1
    else:
        return n*fact2(n-1)
 
 
>>> import timeit
>>> t1 = timeit.Timer(stmt="fact1(20)",setup="from __main__ import fact1" )
>>> t2 = timeit.Timer(stmt="fact2(20)",setup="from __main__ import fact2" )
>>> t1.repeat(3,1000000)
[7.4510148636209408, 7.4105803949943336, 7.4756079334105365]
>>> t2.repeat(3,1000000)
[13.908458197899463, 13.881459515105973, 13.934193591643634]
>>>


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 [:pingouino]


Message édité par masklinn le 20-11-2005 à 17:03:18

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

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.


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
Reply

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 ?

Reply

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.


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
Reply

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. :/

Message cité 1 fois
Message édité par pains-aux-raisins le 20-11-2005 à 18:53:06
Reply

Marsh Posté le 20-11-2005 à 19:03:59    

pains-aux-raisins a écrit :

Masklinn >> flûte, python c'est pourri alors !


[:petrus75]

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 [:petrus75]

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. :/


[:petrus75]


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

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 [:spamafote]

Reply

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...
c'est le progrès quoi [:spamafote]


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 [:petrus75]


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

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 [:petrus75]


Tu m'a pas pris aux sérieux j'espère ?  :heink:
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 ;)


Message édité par pains-aux-raisins le 20-11-2005 à 21:16:57
Reply

Marsh Posté le 21-11-2005 à 01:53:15    

Ben j'ai fait un petit test en OCaml  :pt1cable:  
Voici le source:

Code :
  1. (*#load "nums.cma";;*)
  2. open Num ;;
  3. open String ;;
  4. let n_depart = 20000;;
  5. let rec fact_num_r n accu =
  6.    if  n <=/  (Int 0) then  accu
  7.    else  (fact_num_r ( n -/ (Int 1)) ( Num.( */ ) n accu ) ) ;;
  8. let n_r = Num.Int n_depart;;
  9. let accu_r = Num.Int 1 ;;
  10. let debut_r = Sys.time ();;
  11. let rr = fact_num_r n_r accu_r;;
  12. let fin_r = Sys.time ();;
  13. (*let res_r =
  14.   let x = Num.string_of_num rr in (String.sub x 0 50) ^ "..." ;;*)
  15. let temp_total_r = fin_r -. debut_r;;
  16. let fact_num_i n =
  17.   let result = ref (Num.Int 1) in
  18.   for i = 2 to n do
  19.     result := Num.( */ ) (Num.num_of_int i) !result
  20.    done;
  21.    !result;;
  22. let n_i = n_depart;;
  23. let debut_i = Sys.time ();;
  24. let ri = fact_num_i n_i;;
  25. let fin_i = Sys.time ();;
  26. (*let res_i =
  27.   let y = Num.string_of_num ri in (String.sub y 0 50) ^ "..." ;;*)
  28. let temp_total_i = fin_i -. debut_i;;
  29. (=/) rr ri ;;
  30. "Le résultat comporte: "^(string_of_int (length (Num.string_of_num rr) )) ^(" chiffres" );;
  31. "Temps pour fact de "^(string_of_int n_depart)^" en récursif: "^(string_of_float temp_total_r)^(" sec" );;
  32. "Temps pour fact de "^(string_of_int n_depart)^" en impératif: "^(string_of_float temp_total_i)^(" sec" );;


 
 
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.

Reply

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 :
  1. #include <sys/times.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <gmp.h>
  5. void
  6. fact_rec(unsigned long x, mpz_t *y)
  7. {
  8. if (x == 1) {
  9.  mpz_init_set_ui(*y, 1);
  10. } else {
  11.  mpz_t z;
  12.  mpz_init(z);
  13.  fact_rec(x - 1, &z);
  14.  mpz_mul_ui(*y, z, x);
  15.  mpz_clear(z);
  16. }
  17. }
  18. void
  19. fact_iter(unsigned long x, mpz_t *y)
  20. {
  21. unsigned long i;
  22. mpz_set_ui(*y, 1);
  23. for (i = 1; i <= x; i++) {
  24.  mpz_mul_ui(*y, *y, i);
  25. }
  26. }
  27. int
  28. main(int argc, char **argv)
  29. {
  30. int rc;
  31. char *endptr;
  32. long x, i;
  33. mpz_t y;
  34. struct tms t1, t2;
  35. clock_t cpu;
  36. if (argc != 3) {
  37.  fprintf(stderr, "Usage: fact <n> [i|r]\n" );
  38.  exit(1);
  39. }
  40. x = strtol(argv[1], &endptr, 10);
  41. if (*endptr != '\0' || x < 1) {
  42.  fprintf(stderr, "Invalid number \"%s\"\n", argv[1]);
  43.  exit(1);
  44. }
  45. mpz_init(y);
  46. times(&t1);
  47. if (*argv[2] == 'r') {
  48.  fact_rec(x, &y);
  49. } else if (*argv[2] == 'i') {
  50.  fact_iter(x, &y);
  51. } else {
  52.  fprintf(stderr, "Invalid selector %c\n", *argv[2]);
  53.  exit(1);
  54. }
  55. times(&t2);
  56. cpu = (t2.tms_utime + t2.tms_stime) - (t1.tms_utime + t1.tms_stime);
  57. gmp_printf("%lu! = %Zu\n", x, y);
  58. printf("%lu! has %lu digits\n", x, mpz_sizeinbase(y, 10));
  59. printf("CPU time: %f\n", ((double)cpu)/sysconf(_SC_CLK_TCK));
  60. return 0;
  61. }


Ce qui donne (je ne colle pas les factorielles ici) :

$ ./fact 50000 r
50000! has 213237 digits
CPU time: 3.660000
$ ./fact 50000 i
50000! has 213237 digits
CPU time: 3.460000
 
$ ./fact 123456 r
123456! has 574965 digits
CPU time: 31.920000
$ ./fact 123456 i
123456! has 574965 digits
CPU time: 22.690000


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.


Message édité par matafan le 21-11-2005 à 06:32:18
Reply

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 :
  1. t1=time$("seconds" )
  2. r=fact(20000)
  3. t2=time$("seconds" )
  4. temp=t2-t1
  5. r$=str$(r)
  6. print temp; " sec"
  7. print "longueur : ";len(r$);" chiffres"
  8. wait
  9. function fact(k)
  10.     if k>1 then
  11.         n=k
  12.         do
  13.             n=n-1
  14.             k=k*n
  15.             scan
  16.      
  17.         loop while n>1
  18.     else
  19.         k=1
  20.     end if
  21.     fact=k
  22.     end function


 
resultat pour 20000!
 
125 sec
longueur : 77338 chiffres
 
Pour 50000! il tourne encore .....
 
@++


Message édité par lbasic le 10-12-2005 à 11:13:34

---------------
Liberty BASIC France : http://www.lbasic.fr
Reply

Marsh Posté le 10-12-2005 à 12:20:06    

et voila le resultat !
 
880 sec
longueur : 213237 chiffres
 
no comment please !


---------------
Liberty BASIC France : http://www.lbasic.fr
Reply

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.

Reply

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
:??:


---------------
Doucement le matin, pas trop vite le soir.
Reply

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.

Reply

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+,
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

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 :
  1. -- Sum function for S=X+(x^3/3!)+(x^5/5!).
  2. -- where X expected on command arguments.
  3.  
  4. with Ada.Command_Line;
  5. use Ada.Command_Line;
  6. with Text_Io;
  7. use Text_Io;
  8.  
  9. procedure Main is
  10.  
  11.   subtype My_integer_Type is Long_Long_integer range 0..Long_Long_Integer'Last;
  12.  
  13.   function Facto(Input : in My_Integer_Type) return My_Integer_Type is
  14.   begin
  15.      if Input = 1 then
  16.         return 1;
  17.      else
  18.         return Input * facto(Input-1);
  19.      end if;
  20.   end Facto;
  21.  
  22.  
  23.   X : Integer;
  24.  
  25.   Odd : integer := 3;
  26.  
  27.   S : My_Integer_Type := 0;
  28.  
  29. begin
  30.  
  31.   if Argument_Count /= 1 then
  32.      raise Program_Error;
  33.   end if;
  34.   X := Integer'Value(Argument(1));
  35.   S := My_Integer_Type(X);
  36.   Put_line(Character'Val(13)  & "S=" & My_Integer_Type'Image(S));
  37.   loop
  38.      S := My_Integer_Type(X) +
  39.        (My_Integer_Type(X**Odd)/Facto(My_Integer_Type(Odd)));
  40.  
  41.      Odd := Odd + 2;
  42.      Put_line(Character'Val(13)  & "S=" & My_Integer_Type'Image(S));
  43.   end loop;
  44. exception
  45.   when Constraint_Error =>
  46.      New_Line;
  47.      Put_Line("Argument error..." );
  48.  
  49. end Main;


 
 
Et voici les résultat pour X alant de 1 à 9
 

S= 1
 
S= 1
 
S= 1
 
S= 1
 
S= 1
 
S= 1
 
S= 1
 
S= 1
 
S= 1
 
S= 1
 
Argument error...
 
S= 2
 
S= 3
 
S= 2
 
S= 2
 
S= 2
 
S= 2
 
S= 2
 
S= 2
 
S= 2
 
S= 2
 
Argument error...
 
S= 3
 
S= 7
 
S= 5
 
S= 3
 
S= 3
 
S= 3
 
S= 3
 
S= 3
 
S= 3
 
S= 3
 
Argument error...
 
S= 4
 
S= 14
 
S= 12
 
S= 7
 
S= 4
 
S= 4
 
S= 4
 
S= 4
 
S= 4
 
S= 4
 
Argument error...
 
S= 5
 
S= 25
 
S= 31
 
S= 20
 
S= 10
 
S= 6
 
S= 5
 
S= 5
 
Argument error...
 
S= 6
 
S= 42
 
S= 70
 
S= 61
 
S= 33
 
S= 15
 
S= 6
 
S= 6
 
S= 6
 
Argument error...
 
S= 7
 
S= 64
 
S= 147
 
S= 170
 
S= 118
 
S= 56
 
Argument error...
 
S= 8
 
S= 93
 
S= 281
 
S= 424
 
S= 377
 
S= 8
 
S= 8
 
S= 8
 
S= 8
 
S= 8
 
Argument error...
 
S= 9
 
S= 130
 
S= 501
 
S= 958
 
S= 1076
 
S= 41
 
Argument error...

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed