Calcul de la factorielle d'un nombre avec tous ses chiffres (aucune limite !)

Soyez le premier à donner votre avis sur cette source.

Vue 15 175 fois - Téléchargée 526 fois

Description

Ce code permet de calculer la factorielle d'un nombre et de stocker le résultat dans un fichier *.txt.
La factorielle est calculée avec TOUS ses chiffres, et vous pouvez calculer la factorielle que vous voulez! (aucune limite ) Oubliez TOUT ce que vous avez vu sur ce site en matière de calcul de factorielle, voici LE programme dans ce domaine.

Source / Exemple :

'pour ceux qui ne veulent pas télécharger; mettez cette source dans un bloc-notes et renommez le fichier en *.frm

VERSION 5.00
Begin VB.Form Form1 
   AutoRedraw      =   -1  'True
   BackColor       =   &H00FFC0C0&
   BorderStyle     =   4  'Fixed ToolWindow
   Caption         =   "Calcul de factorielle"
   ClientHeight    =   585
   ClientLeft      =   45
   ClientTop       =   285
   ClientWidth     =   5325
   BeginProperty Font 
      Name            =   "MS Serif"
      Size            =   6.75
      Charset         =   0
      Weight          =   400
      Underline       =   0   'False
      Italic          =   0   'False
      Strikethrough   =   0   'False
   EndProperty
   LinkTopic       =   "Form1"
   MaxButton       =   0   'False
   MinButton       =   0   'False
   ScaleHeight     =   585
   ScaleWidth      =   5325
   ShowInTaskbar   =   0   'False
   StartUpPosition =   2  'CenterScreen
   Begin VB.TextBox Text1 
      BeginProperty Font 
         Name            =   "Tahoma"
         Size            =   8.25
         Charset         =   0
         Weight          =   400
         Underline       =   0   'False
         Italic          =   0   'False
         Strikethrough   =   0   'False
      EndProperty
      Height          =   285
      Left            =   1680
      TabIndex        =   1
      Top             =   120
      Width           =   2295
   End
   Begin VB.CommandButton Command1 
      BackColor       =   &H00FFC0C0&
      Caption         =   "Calculer"
      BeginProperty Font 
         Name            =   "Tahoma"
         Size            =   8.25
         Charset         =   0
         Weight          =   400
         Underline       =   0   'False
         Italic          =   0   'False
         Strikethrough   =   0   'False
      EndProperty
      Height          =   375
      Left            =   4200
      Style           =   1  'Graphical
      TabIndex        =   2
      Top             =   120
      Width           =   855
   End
   Begin VB.Label Label1 
      Appearance      =   0  'Flat
      BackColor       =   &H00FFC0C0&
      Caption         =   "Factorielle à calculer"
      BeginProperty Font 
         Name            =   "Tahoma"
         Size            =   8.25
         Charset         =   0
         Weight          =   400
         Underline       =   0   'False
         Italic          =   0   'False
         Strikethrough   =   0   'False
      EndProperty
      ForeColor       =   &H80000008&
      Height          =   255
      Left            =   120
      TabIndex        =   0
      Top             =   120
      Width           =   1575
   End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'définition des variables
Dim N, R(100000), M, MAX, K, RET, S, B, A, C2, C1, E4, E5, B2, L, L1, C, bouc1, bouc2, bouc3, bouc4, CX, CY As Double
Dim ef As String
Dim MAIN As Double  'pour rendre la main

Private Sub Command1_Click()
If N <= 0 Then MsgBox "Nombre incorrect", vbCritical: Text1.Text = vbNullString: Exit Sub 'vérification de N
'initialisation des variables
R(1) = 0.00001: M = 2: CX = 0: CY = 0: bouc1 = 1: bouc2 = 1: bouc3 = 1: bouc4 = 1: MAX = 1: E5 = 100000: E4 = 10000

Do While M <= N

DebutWhile:
    
    'compteur pour rendre la main de tps en tps
    MAIN = MAIN + 1
    If (MAIN Mod 100000) = 0 Then
        DoEvents
        Me.Caption = (M / N * 100) & " %"   'a enlever pour ceux qui veulent + de speed
    End If
    
    CAl1    'premiere série de calculs
    
    If B2 >= E4 Then
        'deuxième série
        B2 = B2 / E4
        RET = Int(B2)
        R(K) = Int(0.5 + (B2 - RET) * E4) + C1
        K = K + 1
        If K <= MAX Then GoTo DebutWhile
        R(K) = RET / E5
        MAX = MAX + 1
        If MAX > 10000 Then End
        GoTo Increm
    End If
    
    R(K) = B2 + C1
    RET = 0
    
    If K <> MAX Then
        K = K + 1
        GoTo DebutWhile
    End If
    
Increm:
    'incrémentation de M; fin de la 'multiplication'
    M = M + 1: K = 1: RET = 0
Loop

For K = MAX To 1 Step -1

    S = Int(0.5 + R(K) * E5)
    
    If S = 0 Then
        L = 8
    Else
        L = 8 - Int(Log(S + 0.5) / Log(10))
        If L = 0 Or K = MAX Then GoTo CreateString
    End If

    For L1 = 1 To L
        If (L1 Mod 500) = 0 Then DoEvents   'rend la main de tps en tps
        ef = ef & "0"
    Next L1
    DoEvents    'pour le cas ou L<500
    
CreateString:
    ef = ef & S 'rajoute le nouveau chiffre S au résultat
Next K

CreateFile  'résultat

End Sub

Private Sub Text1_Change()
'récupération de N en fct de text1.text
N = Int(Val(Text1.Text))
End Sub

Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer)
'appui de 'enter', donc lancement des calculs
If KeyCode = 13 Then Call Command1_Click
End Sub

Private Sub CAl1()
'première série de calculs
'les commentaires 'mathématiques' n'aparaissent pas encore, puisque
'je remet à jour cette source que j'ai fait il y a très longtemps, et que
'donc j'ai perdu le fil de mon algorithme
'mais çà viendra ds la prochaine mise à jour

bouc1 = bouc1 + 1
S = R(K)
B = Int(S)
A = Int(E5 * (S - B) + 0.5)
C = (RET + A * M) / E5
C2 = Int(C)
C1 = Int(E5 * (C - C2) + 0.5) / E5
B2 = B * M + C2

End Sub

Private Function CreateFile()
'fin des calculs et création du fichier texte
Open App.Path & "factorielle de " & N & " .txt" For Output As #1
    Print #1, ef    'écriture
Close #1
MsgBox "Le fichier a été créé dans " & App.Path, vbOKOnly
End 'fin
End Function

Conclusion :

le source est de moi, désolé si il est pas commenté

ah oui, le fichier résultat créé est stocké dans le répertoire du programme

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
7
Date d'inscription
dimanche 4 juin 2006
Statut
Membre
Dernière intervention
15 octobre 2006

Erreurs non vues à la fin de meesage :
Dernires remarques concernant le calcul scientique, il faut lire :
À noter que les plate-formes Solaris ont une précision (pour le même type de variables) ayant le double de décimales par rapport aux PC.
Messages postés
7
Date d'inscription
dimanche 4 juin 2006
Statut
Membre
Dernière intervention
15 octobre 2006

Je m'excuse de vous avoir réveillé mais si je connais si bien le sujet c'est parce que je n'ai pas les moyens de me payer Maple ou un équivalent. J'ai donc dû développer ma propre application de calcul scientifique (j'en suis encore au noyau de base) mais en Java (même raisons que Maple) qui est également orienté web.
J'apporte cette précision car mon commentaire n'en laisse rien paraître. Mais la façon et les résultats obtenus sous Java sont proportionnellement similaires à ceux obtenus sous d'autres langages. Pourquoi Microsoft a sorti la plate-forme .NET si Java est aussi lent que certains le prétendent ?
Quant aux tableaux de chaînes ils ne sont intéressants que si l'on y met des valeurs distinctes pour un calcul. Exemple :
sommeCumulée(String[] arguments)
Une somme de plusieurs éléments sera implémentée en utilisant ce code Java schématique :
String somme(String[] listeArguments){
x = liste.length; // nombre d'éléments en entrée
y = sommeCumulée(liste); // résultats initiaux
résultat y[x]; // résultat dernier de la liste
}
C'est du naïf mais on ne réécrit pas de code existant. Mais avec de multiples fichiers cela devient ingérable à cause de la quantité de RAM nécessaire 2 Go pour le fichier + XP et ce avant de faire un calcul avec ce fichier... On voit donc que les valeurs que j'ai données sont purement théoriques. En fait il faudrait s'en tenir à une valeur moyenne abordable pour toutes les machines, le Go semble être la meilleure.

Remarques sur la factorielle
Je viens de passer pas mal de temps à accélerer mon noyau naïf mais j'ai eu droit à de belles surprises mais l'opération n'est pas terminée
1- L'algorithme classique va de X vers 0. J'ai obtenu le temps suivant pour 1500 : 89 secondes avec int[]. En montant de 1 vers x : 34 secondes ! soit -60%. En conclusion plus on augmente progressivement la taille du résultat plus le calcul est rapide.
2- Le passage du type int[] à long[] permet seulement de passer de 34 à 21 secondes soit -40% (= 75% au total). Plus on utilise une grande valeur entière moins la performance progresse.
3- L'algorithme en lui-même est trop lent. Exemple :
1! = 1 // classique
2! = 1*2 // classique
3! = 1*2*3 // classique
4! 1*2*3*4 1*2^3*3 // modifié
5! 1*2*3*4*5 1*2^3*3*5 // modifié
6! 1*2*3*4*5*6 1*2^4*3^2*5 // modifié
Le secret s'appelle la factorisation, l'on se contente de simplifier les multiples de 2 le gain est d'un peu de 50% à cause du calcul de la puissance de 2. Et plus il y a de multiples plus il faut prévoir leurs interactions...
Je n'ai pas essayé mais cela doit en valoir le coup mais j'ai d'autres projets en tête.

À US_30 : au quotidien à cause du temps de calcul et pour être franc j'ai un Athlon XP 2600 en 32 bitsà 2 GHz. Trouve moi une application 64 bits de calcul si tu en trouves parce que même en dehors de ce domaine c'est Apple contre PC...
Les erreurs d'arrondis viennent du fait que les nombres réels contiennent beaucoup de nombres infinis (quand ils ne sont pas transcendants). Il faut donc éviter les approximations et faire du calcul exact comme les Texas (89 et 92 entre autres), ce qui est loin d'être une promenade de santé.

À VIOLENT_KEN : mon programme est comme le tiens : mon premier projet informatique. Et comme tu l'auras compris c'est pour le quotidien. Et au vu des résultats le tien est plus rapide mais j'utilise mon noyau de calcul à base de String et de long[] et la multiplication n'est pas optimisée.
Si tu n'as pas compris la remarque sur le cast, c'est parce que tu ne sais pas ce qu'est un cast, ou en français, une conversion de type. J'espère que mes explications te seront utiles et sont basées sur mon code en Java. Exemple (calcul de 10^x, x positif):
static String pow10(String x, String y){
int z = Integer.parseInt(y); // conversion de String vers entier
int j = (int) Math.floor(y / 10);
String result = x;

if (j != <0)
for (int i = 0; i < j i++)
result = result.concat("0000000000");

j = z - result.length();
result = result.concat(ZEROS[j]);
return result;
}
Zeros[] est une chaîne Static située en dehors de la méthode mais dans sa classe. Static permet de l'utiliser dans les méthodes de la classe. Elle comporte 10 chaînes, la première est vide, à la suivante on a "0", puis à chaque fois on ajoute un zéro, la dernière en a neuf.
Bien que ce soit du Java le code est clair sauf :
int j = (int) Math.floor(y / 10);
Parce que les tableaux sont basés sur des nombres entiers il nous en faut un. Sans le cast Java plante au débogage parce que Math.floor retourne un double. Remarques les deux int en entrée !
En fait tous les langages de programmation le font. Je te donnerai la règle plus tard. Pour passer de double à int on réalise un cast qui est dit "explicite". Ce type de cast est réalisé par le développeur, mais pas ce cast dit "implicite" qui lui se fait automatiquement comme pour Math.floor.
La règle des casts implicites est la suivante :
flottant flottant = flottant (le plus grand en entrée)
entier flottant = flottant
entier entier = entier (le plus grand en entrée)
Le plus grand en entrée veut dire que s'il y a un 16 et un 32 bits en entrée la sortie doit être en 32 bits. À noter que l'on peut aussi faire un cast dit de "réduction". C'est-à-dire que l'on réduit le nombre de bits du type primitif.
J'espère que ce n'est plus incompris pour toi.

Dernière remarque concernant le calcul scientifique :
Le premier langage de programmation (le Fortran apparu en 1954) est encore très utilisé dans les labo à cause de sa facilité d'apprentissage et il n'a pas 16 décimales en précision mais accélère les simulations numériques. À noter les plate-formes sont ont une précision (pour le même type de variables) ayant le double de décimales par rapport aux PC.
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Merci pour cette précision.


Donc on doit se rabattre (même si c'est relativement moche) sur la création de n fichiers de 2Go chacun contenant tous une partie du nombre calculé.

@+
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
23
L'espace mémoire accordé au processus en mode normal (hors switch 3 Go sur system serveur) est de 2 Go system 32 bits, les 2 autres Go sont réservés à la zone kernel.
String dynamique ou non n'y changera rien.
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Ceci :
"Dim N, R(100000), M, MAX, K, RET, S, B, A, C2, C1, E4, E5, B2, L, L1, C, bouc1, bouc2, bouc3, bouc4, CX, CY As Double "

est inadmissible ;)

J'aurais bien updaté cette source si j'avais eu le temps...

@+
Afficher les 18 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.