IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Macros et VBA Excel Discussion :

Optimiser macro : problème d'Euler n°12


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Ingénieur BE
    Inscrit en
    Avril 2014
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur BE
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 26
    Par défaut Optimiser macro : problème d'Euler n°12
    Bonjour,

    J'essaye tant bien que mal de résoudre le problème d'Euler n°12 (https://projecteuler.net/problem=12)

    Mon problème, c'est que ma macro est trop gourmande en calcul et du coup, vraiment longue à s'exécuter.
    A chaque lancement de la macro, Excel tombe en mode "ne répond pas" et j'ai pas eu la patience d'attendre plus de 4min après le lancement de la macro. Avec un Ctrl+Pause aux environs de 4min, j'en suis au nombre triangulaire 7 279 020 qui admettrais (au moins) 142 diviseurs.

    Mon programme semble fonctionner pour de petits nombres, donc ma question n'est pas de trouver une réponse au problème n°12, mais plutôt de m'aider à réduire le temps d'exécution de ma macro.


    mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    Sub prob12()
     
    Dim a As Long
    Dim nb_diviseur As Long
    Dim diviseur As Long
    Dim nb_triangle As Long
     
    a = 3
    nb_triangle = 3
     
    For a = 3 To 20000000
     
        diviseur = 1
        nb_diviseur = 0
        Do While nb_diviseur < 500
     
            If nb_triangle Mod diviseur = 0 Then
                diviseur = diviseur + 1
                nb_diviseur = nb_diviseur + 1
            Else
                If diviseur > nb_triangle / 2 Then
                    nb_diviseur = nb_diviseur + 1
                    Exit Do
                Else
                    diviseur = diviseur + 1
                End If
            End If
     
        Loop
        If nb_diviseur >= 500 Then
            MsgBox nb_triangle & " est le premier nombre triangulaire admettant plus de 500 diviseurs"
            End
        End If
        nb_triangle = nb_triangle + a
    Next
     
     
    End Sub

    Merci d'avance pour vos conseils

    Mayeux67

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 266
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 2 266
    Par défaut
    Bonjour,

    vu que tu travailles avec des entiers ça va être assez difficile d'accélérer en gardant le même algorithme je pense.
    Une proposition : tu pourrais essayer en décomposant en facteurs premiers et en construisant une table de nombres premiers au fur et à mesure.
    eric

  3. #3
    Inactif  

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2012
    Messages
    4 903
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2012
    Messages : 4 903
    Billets dans le blog
    36
    Par défaut
    Bonjour,

    Tu ne dois pas oublier que VBA est un langage interprété et non un langage compilé. Puisque chaque instruction est interprétée chaque fois qu'elle doit être exécutée (une boucle de 10 instructions exécutée 10 fois donne 100 conversions en langage-machine) la meilleure façon d'optimiser un programme est probablement de réduire le nombre d'instructions, en utilisant le meilleur algorithme disponible.

  4. #4
    Membre averti
    Homme Profil pro
    Ingénieur BE
    Inscrit en
    Avril 2014
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur BE
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 26
    Par défaut
    Bonjour,

    Merci pour vos réponses,

    @eriiic : une décomposition en facteurs premiers me donnerait, pour un nombre donné, une liste de nombres premiers. Il faudrait alors que je compose avec cette liste pour trouver tous les diviseurs du nombre donné .. On gagnera certes du temps en faisant la décomposition en facteurs premiers mais la recherche de tous les diviseurs à partir de cette décomposition me parait un peu compliqué non ?

    D'autant plus qu'avec mon niveau actuel de VBA, je ne sais pas utiliser de tableau, et encore moins un tableau dynamique ..

    Je vais néanmoins travailler sur cette idée, mais il me faudra de l'aider pour créer la code qui gère le tableau (entre autre)

    @clementmarcotte : j'avais bien saisi qu'une boucle dans un boucle ça fait faire plus de travail à la machine C'est pour ça que je suis venu ici pour avoir des conseils, parce que d'un coté, mes connaissances en VBA me permettent pas pour le moment d'améliorer cet algorithme, et de l'autre coté, mes connaissances en maths sont un peu rouillées pour élaborer un autre algorithme.

    Est-ce que par exemple séparer les boucles permettrait de réduire le temps d'éxecution ? dans un premier temps chercher les nombres triangulaires et les stocker dans un tableau et après faireun boucle à part pour tester ces nombres triangulaires et leurs nombres de diviseurs. Si on trouve aucun résultat qui à plus de 500 diviseurs, on augmente le nombre de nombre triangulaire à chercher dans la 1° boucle ?


    ++
    Mayeux67

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 266
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 2 266
    Par défaut
    Bonjour,

    Est-ce que par exemple séparer les boucles permettrait de réduire le temps d'éxecution ? dans un premier temps chercher les nombres triangulaires et les stocker dans un tableau et après faireun boucle à part pour tester ces nombres triangulaires et leurs nombres de diviseurs.
    Peut-être, tout dépend si tu ne perds pas plus de temps dans la recherche des diviseurs. Là aussi te générer une table des nombres premiers te fera gagner un temps considérable.

    Pour générer tes nombres triangulaires utilises somme des n premiers entiers = n(n+1)/2 plutôt que de balayer tous les nombres.

    eric

  6. #6
    Membre averti
    Homme Profil pro
    Ingénieur BE
    Inscrit en
    Avril 2014
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur BE
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 26
    Par défaut
    Re,

    Je n'avais pas pensé à utiliser n(n+1)/2, merci pour le tuyaux

    Concernant le tableau des nombres premiers, j'ai déjà une macro qui me donne le Xieme nombre premier que je peux modifier pour les besoins de ce problème.
    Pour le tableau, voici un bout de code pour l'utilisation du dit tableau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Dim tblnbprem() As Integer
    Dim i As Integer
    ReDim tblnbprem(i + 1)
    tblnbprem(i) = nbre 'nbre est le nombre premier de rang i
    le redim et l'affectation seront placé dans une boucle qui me calcul le nombre premier n°i.
    Est-ce que je peux déjà partir sur un tableau de ce type ? niveau syntaxe il est bien définit ?

    Merci d'avance,
    Mayeux67

Discussions similaires

  1. {VBA Excel} Optimiser macro si possible
    Par Thomas69 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 05/06/2007, 16h06
  2. [Macro] Problème d'affectation à un bouton
    Par aigleborgne dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 04/06/2007, 09h18
  3. [Macro] problème de macro
    Par pouii dans le forum IHM
    Réponses: 2
    Dernier message: 02/05/2007, 13h58
  4. [Macro]Problème d'importation .CSV avec macro
    Par Eric Harvey dans le forum VBA Access
    Réponses: 8
    Dernier message: 12/04/2007, 17h04
  5. Optimisation ou problème d'index
    Par Erakis dans le forum SQL Procédural
    Réponses: 35
    Dernier message: 02/06/2006, 19h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo