|
Publicité | |||||||||||||||||||||||
|
|
#1 | ||||||
|
Invité régulier
![]() Inscription : août 2009 Messages : 140 ![]() |
Bonjour,
J'ai débuté le codage sous VBA depuis pas longtemps, et je rencontre actuellement pour plusieurs de mes codes un problème récurrent. Lorsque je fais une boucle FOR quelconque, mais répétitive: je sui obligé d'écrire : Code :
Code :
J'essaie donc de simplifier pour le dernier exemple par exemple, avec: Code :
... et pas de bol misterVBA connait pas la fonction magique INDIRECT() Mes recherches sur google n'ont donné que des cas liés aux noms de feuilles, ou choper une valeur via une adresse(Range(Range())), ce qui n'est pas du tout le cas ici... En résumé, comment convertir une chaîne string en référence (d'un objet déjà existant) ? (dans mes codes, les objets sont en général des tableaux de type Variant/Variant) Merci d'avance pour vos réponses. Dernière modification par Masamunai ; 14/03/2010 à 14h30. |
||||||
|
|
00
|
|
|
#2 | ||
|
Membre Expert
![]() Inscription : juillet 2007 Messages : 2 134 ![]() |
Salut Masamunai et le forum
Tu comme ci et si ça ne marche pas, tu fais comme ça Et si tu ne comprends pas, alors explique clairement ce que tu veux, pas la manière que tu utilises, mais le but. On ne peux simplifier une macro, il faut savoir ce qu'elle doit faire. La méthode utilisée n'est intéressante que pour éviter de l'avoir en réponse. Code :
Select Case est intéressant pour assurer un certain nombre de test, mais si tu ne veux que tester une seule valeur, un simple If suffit. A+ |
||
|
|
00
|
|
|
#3 | ||||
|
Invité régulier
![]() Inscription : août 2009 Messages : 140 ![]() |
A ben désolé si je n'ai pas été clair malgré le titre du topic et 2 exemples... mais merci pour ta réponse.
Mon but est simple en fait: je cherche à simplifier/optimiser mes codes, et là la 1ère chose que je remarque sont les répétitions, lesquelles sautent pourtant aux yeux :S Dans le 1er exemple c'était les "Tablei" , est il possible de ne faire qu'une seule boucle "nommant" chaque tableau Tablei avec le bon integer i ? Dans le 2e exemple, on voit une liste de 40 "Case is", mais on remarque que les appels de procédures "Resulti" ont le même indice que les "Case i" (et cet indice = Ne c'est cool ^^), là encore est-il possible de faire une boucle pour simplifier tout ça ? Le problème est qu'à chaque fois que j'essaie d'écrire une boucle du genre : Code :
Code :
Ce serait plus simple, non? Mais dans les 2 exemples, j'obtiens des erreurs d'incompatibilité de type ou d'objet "inconnu", alors que les Tablei et les procs Resulti sont déjà construites, définies etc... (les codes initiaux marchent d'ailleurs). Voilà pourquoi je comprends pas très bien alors que la concaténation de ces noms semble se faire correctement mais apparemment VBA est pas foutu de savoir que -par exemple- pour i=7, ("Result" & i)=Result7 corresponds à un appel à la procédure nommée Result7, ou encore que "Table" & i = Table7 corresponds au tableau de nom Table7, etc... Je viens de passer l'après-midi a tenter avec une variable intermédiaire déclarée en Variant, avec .Object.Name, avec .Find, ... aucune méthode ne pige un nom concaténé >< je suis à court d'idées là ;; EDIT: je précise qu'il n'y a aucun private, ce sont des codes vraiment basiques. EDIT2: s'il y a vraiment besoin, je peux toujours poster les fichiers correspondants à ces 2 bouts de code (m'a pas semblé nécessaire vu qu'il ne s'agit qu'une histoire de syntaxe toute bête mais fort énervante pour un débutant comme moi) Dernière modification par Masamunai ; 14/03/2010 à 18h57. |
||||
|
|
00
|
|
|
#4 | |||
|
Expert Confirmé Sénior
![]() |
Salut
Ce qui est claire a tes yeux par ce que tu as le nez collé sur ton problème, ne l'ai pas forcement pour nous qui te lisons. Ceci etant dis Pour ton 1er problème Code :
Qwaz Oulala wala j'avais pas tout lu.... Citation:
![]() ![]() En somme si tu as ce type de problème ça n'est pas lier a un problème venant du langage, mais a un problème lier a la construction de tes procédures Tu dois rendre ta procédure polyvalente afin qu'elle gère tous les cas lié a un numéro Ne. Montre nous l'intérieur de ces multiple procédure qui on certainement toutes le même code. A++ Qwaz
__________________
MagicQwaz := Harry Potter la baguette en moins ![]() Le monde dans lequel on vit HammerFest Score PowerBall Gyroscope Green : 11847 Dernière modification par AlainTech ; 09/05/2010 à 14h29. Motif: Fusion de 2 messages |
|||
|
|
00
|
|
|
#5 |
|
Invité régulier
![]() Inscription : août 2009 Messages : 140 ![]() |
Oula je n'avais pas vu votre réponse super rapide Qwazerty.
Ok ci-joint les 2 fichiers contenant le + de "répétitions" dont je cherche à simplifier. Les 2 traitent la même chose: générer des permutations avec SommeMatching, et on été développées en partenariat avec le forum VeriTi.net et plus spécialement Marco57. Le 1er est ma dernière version, tandis que le 2e est celui de Marco qui comme vous le verrez semble bien + "pro" :p Bref là n'est pas la question. Je souhaiterait apprendre à éviter les répétitions de codes (qui entraineront peut etre un gain de vitesse d'éxécution), mais je me heurte à ce qui semble être un banal problème de syntaxe... que j'aurais réglé sans problème avec la fonction INDIRECT() sous Excel, mais sous VBA ben.... Vous trouverez donc dans ces 2 fichiers, outre les 2 exemples précités, plein d'autres répétitions "lourdes" à lire. En espérant que cela vous aide à y voir plus clair. (désolé si j'ai trop simplifié le post d'origine) Dernière modification par Masamunai ; 18/03/2010 à 09h57. |
|
|
00
|
|
|
#6 | ||
|
Expert Confirmé Sénior
![]() |
Re
Pour le debut Code :
++ Qwaz
__________________
MagicQwaz := Harry Potter la baguette en moins ![]() Le monde dans lequel on vit HammerFest Score PowerBall Gyroscope Green : 11847 |
||
|
|
00
|
|
|
#7 |
|
Invité régulier
![]() Inscription : août 2009 Messages : 140 ![]() |
a oui tu as raison, j'aurais du m' "entrainer" sur ce bout là... je me cassait les dents sur le bout de code se trouvant à la fin, avec les lignes des transpose(Table).
Merci beaucoup pour ce début de réponse, on dirait qu'il faut que je mette mes noms concaténés entre parenthèses d'un type donné pour qu'ils soient reconnus par VBA, si j'ai bien compris ? (comme Range("Dest" & i) ) |
|
|
00
|
|
|
#8 | ||
|
Expert Confirmé Sénior
![]() |
Essais d'expliquer un peu plus le but du code, car perso j'ai du mal a mis retrouver dans toutes ces boucles.
Instinctivement au vu des résultat et de la structure des boucles, je dirais que seul la dernière la plus longue doit être conservée, les autre boucle retourne un résultat partiel. On garde a chaque fois x valeurs en partant de la droite, x étant le nombre d'uplets (défini UpLets s'il te plait) et on supprime les doublons. Juste pour info, c'est quel jeu? Lineage2 peut être? une piste de simplification; si tu reproduit la meme chose sur toutes tes boucle ca réduira deja un peu la taille, a toi de voir si les résultats obtenus sont cohérents. Code :
A++ Qwaz
__________________
MagicQwaz := Harry Potter la baguette en moins ![]() Le monde dans lequel on vit HammerFest Score PowerBall Gyroscope Green : 11847 |
||
|
|
00
|
|
|
#9 | ||
|
Invité régulier
![]() Inscription : août 2009 Messages : 140 ![]() |
Pour l'application, cela n'a rien à voir avec un jeu, c'est pour un des services de ma boîte dans le cadre d'une simulation.
Pour le principe, il s'agit de connaître la probabilité globale pour un certain nombre d'essais, en utilisant que certaines valeurs connues (chacune ayant sa propre probabilité d'apparition). Ces essais sont alors représentés sous forme de "X-uplets", par exemple un 5-uplet = 5 essais indépendants consécutifs, cela en utilisant que 9 chiffres possibles présentés en ligne dans les fichiers, avec leurs probas respectives juste en-dessous. En termes d'implémentation, j'avais d'abord fait un code générant toutes les permutations possibles à partir des nombres dont la probabilité individuelle est non-nulle. Je me suis retrouvé très vite limité à des 6-uplets en n'utilisant que 3 chiffres à proba non nulle... saturation mémoire au delà. Or la simulation nécessite de pouvoir tester avec 9 chiffres à proba non nulle, et pour des X-uplets pouvant aller assez "loin", càd ~30... J'ai donc "réduit" cette génération en me basant sur la propriété que les permutations avec répétition sont en fait des permutations simples à partir de combinaisons avec répétitions, lesquelles sont beaucoup moins nombreuses à générer. Un exemple est expliqué à l'adresse http://fr.wikipedia.org/wiki/Combina...9p%C3%A9tition. Vers la fin, juste avant les algos, il y a un tableau permettant de visualiser comment générer ces combinaisons avec répétitions, je me suis donc basé sur ce tableau-exemple pour coder les 15 boucles que vous voyez dans mon fichier. Ensuite, ces combinaisons ne représentant qu'une partie de la solution souhaitée, il restait à trouver les permutations simples issues de celles-ci. Là par contre, pas besoin de les générer, on a juste besoin de leur nombre, lequel est défini sur wikipedia aussi, et est calculé puis affiché en 3e colonne à côté de chaque uplet généré. J'ai également utilisé un "seuil" recherché : il s'agit tout simplement de la somme des membres d'un uplet. Donc si au cours d'une boucle, les chiffres utilisés pour "former" un uplet ont une somme différente de ce seuil SommeCible => on reboucle chiffre suivant, sans former l'uplet en question qui est alors "rejeté". Pas besoin de routine de suppression, et aucun risque de doublon. Enfin, Marco de Veriti.net m'a aidé pour la mise en forme de ces boucles et appris pas mal de trucs, en particulier pour implémenter ce seuil "SommeCible". Au final, on arrive déjà à arriver jusqu'aux 15-uplets sans trop trop "ramer". Exemple: j'ai "0" "1" et "5" avec respectivement 10% 86.7% et 3.3% de chances d'apparition, quels sont donc les Xuplets possibles avec répétition possible, pour avoir un seuil SommeCible=6 ? La macro génére donc seulement (pour les triplets): Code :
(051) (105) (150) -> 4 permutations avec répétition au total respectant la somme = 6. Enfin, dans le tableau résultats on sommeprod les probas résultantes de chaque Xuplet généré avec son nombre. Ce tableau résultats sera ensuite intégré dans la simulation, laquelle envoie aussi les paramètres en entrée (chiffres à utiliser, SommeCible et probas). Donc oui le fichier fonctionne, mais alors j'ai attrapé pas mal de crampes aux doigts à copier-coller toutes ces boucles... je me suis arrêté "que" à 15 :s Marco lui a été plus loin jusqu'à 40 Bref, là je vois pas trop comment faire mieux, à part continuer à étudier le fichier de Marco, et supprimer ces boucles répétitives en espérant un gain en optimisation (et lisibilité). C'est l'objet de ce post ici. |
||
|
|
00
|
|
|
#10 |
|
Expert Confirmé Sénior
![]() |
Salut
Je n'ai pas tout lu, je regarderai ce soir. Mais je pense avoir une solution de boucle polyvalente (je savais bien que la nuit porte conseil Pour ton problème de saturation, au lieu d'utiliser 15 tableau, il serait plus judicieux d'en utiliser 1 seul puis a chaque fois qu'une boucle for actuel est fini tu inscrit les résultat dans le tableau excel, ainsi pour les calcule suivant tu réutilises le même tableau que tu auras vidé au préalable. Concrètement a l'heure actuel il faudrait mettre chaque lige transpose sont la boucle qui rempli le tableau associé et vider ce tableau associé pour libéré de la mémoire. Donc la question est veux tu calculer toutes les solutions ? Si j'ai saisi, il suffirait de faire a chaque fois les boucles de 0 à N et non plus de Xn-1 à N comme actuellement? A++ Qwaz
__________________
MagicQwaz := Harry Potter la baguette en moins ![]() Le monde dans lequel on vit HammerFest Score PowerBall Gyroscope Green : 11847 |
|
|
00
|
|
|
#11 | |
|
Invité régulier
![]() Inscription : août 2009 Messages : 140 ![]() |
Bonjour,
Pour ta question en gras, relis l'explication de mon post au dessus stp, en particulier les conditions utilisées pour limiter la génération (Combi seules + SommeMatching). Il y a aussi plein de commentaires dans les fichiers excel ET dans le code VBA. Ces 2 conditions se voient également dans TOUTES les boucles aussi... Cependant, pour des raisons de déboguage, oui il est utile de voir tous les uplets générés pour voir si le code fonctionne, c'est pour ça que tu vois à l'intérieur de toutes ces boucles un If SommeCible=0 supplémentaire, alors qu'il s'agit de l'objectif à atteindre (donc forcément > de 0). Je suis effectivement d'accord avec toi d'avoir eu le même "feeling" qu'il serait tout à fait possible de remplacer toutes ces boucles par quelque chose de "polyvalent" comme tu dis. Mais, outre mes connaissances très limitées en VBA, ces boucles sont particulières pour 2 raisons: a) Si tu a suivi le tableau sur wikipedia, tu t'apercevra que ces boucles sont en fait "rétrécissantes" à chaque rebouclage, càd que quand la dernière boucle (la plus basse x0) a fini, il y a un set de cette variable x0min à +1, ce qui fait que la boucle suivante bouclera 1x moins. pareil pour les autres for au dessus dans la même boucle. b) Quant on passe d'une boucle à la suivante, pour générer l'uplet suivant, il faut rajouter une variable xN de plus, distincte des autres, vu que l'uplet a 1 membre de plus. Si tu raisonnes dans le sens inverse, càd garder la plus grosse (et y en a pas en fait vu que c'est moi qui me suis arrêté à 15, pourrait très bien être 30 ou 40?), je ne suis pas sûr de deviner comment tu compterait faire... Bref si: Citation:
Remplacer ca ça par quelquechose sans For ? honnetement je vois pas du tout concretement, j'ai hâte à ce soir ![]() EDIT: oula j'avais pas vu quelquechose dans ton format de boucle précédent post : xN = xN+1. J'essaie et je post si résultats toujours cohérents. EDIT2: ok les résultats sont toujours les mêmes avec cette astuce, Merci bcp Qwaz
Dernière modification par Masamunai ; 15/03/2010 à 12h54. |
|
|
|
00
|
|
|
#12 | ||||
|
Invité régulier
![]() Inscription : août 2009 Messages : 140 ![]() |
En attendant ce soir j'ai essayé d'appliquer tes conseils de syntaxe :
Code :
Code :
|
||||
|
|
00
|
|
|
#13 | ||
|
Expert Confirmé Sénior
![]() |
Salut
Petite réponse vite faite, comme je e l'ai dis je n'ai pas eu le temps de regarder le lien wiki, ni mm de pris le temps de bien lire tes dernières post. J'avais edité un message et donc tu as du passer a coté, j'expliquer la notion de Xn-1 à N j'avauis posté ce type de boucle Code :
Pour l'histoire des tables que tu dois trainer jusqu'à la fin, je dirais que non, il suffit de garder en mémoire le critère qui t'intéresse, par exemple le tableau est il vide, oui - non, stocker ce type d'info ne tiens pas de place comparait a trainer un tableau rempli jusqu'à la fin uniquement pour savoir si celui ci est vide ou non. Mais ce n'est qu'un exemple il faut voir ce qu'il faut tiré du tableau exactement. ++ Qwaz
__________________
MagicQwaz := Harry Potter la baguette en moins ![]() Le monde dans lequel on vit HammerFest Score PowerBall Gyroscope Green : 11847 |
||
|
|
00
|
|
|
#14 |
|
Invité régulier
![]() Inscription : août 2009 Messages : 140 ![]() |
Oui en effet, j'étais passé à côté de ton astuce, mais je viens de l'essayer ce matin et ça fonctionne
Merci.Petite parenthèse: j'avoue que je suis branché sur un jeu online, Final Fantasy XI, dont je développe d'ailleurs un outil Excel permettant de faire des choix d'équipements (une sorte de comparateur par calcul de dommages). J'ai d'ailleurs posté 2 autres topics sur ce forum à http://www.developpez.net/forums/d89...requentielles/ et http://www.developpez.net/forums/d88...lasseur-excel/ EDIT: Bon je poste la v4 modifiée avec les simplifications de boucle et des Destinations. Le constat est sans appel: pour un même calcul demandé, la version "simplifiée" est 10x plus .... lente que celle codée "en dur". No comprendo Dernière modification par Masamunai ; 15/03/2010 à 15h00. |
|
|
00
|
|
|
#15 | ||
|
Expert Confirmé Sénior
![]() |
Salut
Alors voila le principe Code :
MaxN : correspondant a ton N dans ton code NbrUplet : Nombre de boucle a réaliser (Avec ton ancien code pour un Uplets 3, tu avait 3 boucles for, ici la fonction reproduira tes 3 boucles for. Si tu me dis que la boucle for précédente fonctionne, alors il y a de grandes chances que celle ci aussi. Il reste à coder la parti remplissage du tableau et a l'intègrer dans ton code d'origine. A++ Qwaz
__________________
MagicQwaz := Harry Potter la baguette en moins ![]() Le monde dans lequel on vit HammerFest Score PowerBall Gyroscope Green : 11847 |
||
|
|
00
|
|
|
#16 |
|
Invité régulier
![]() Inscription : août 2009 Messages : 140 ![]() |
o.O je n'avais pas vu 2e page lol
Ok merci beaucoup, je vais regarder ça tout de suite. Edit: bon... après lecture de cette explication... je reste sceptique pour les raisons suivanes: a) ce n'est pas NbrUplets, mais NbMembres (sous-entendu max par uplet). S'il y en a 15 demandés, ce que le dernier type d'uplet sera de type à 15 chiffres. Rien à voir avec le dénombrement d'uplets. Dans le code, ce Nbmembres est noté NbM (et cNbM pour NbM corrigé pour l'anti-saturation) b) Pourquoi faire "à l'envers" ? surtout si on doit afficher les résultats des uplets générés au fur et à mesure ce serait 10x mieux (et + lisible) de commencer par les uplets de poids faible, puis monter en puissance ? et aussi pour des raisons de test d'arrêt non ? Ces deux raisons font que je pense que je devrais te laisser le temps de bien assimiler les choses En revanche, l'idée de mettre tous les x0, x1, x2, ... , xN de ces boucles dans un tableau intermédiaire qui serait appelé à chaque appel de la fonction, puis redimensionné correctement, avant d'attaquer le "traitement" proprement dit, me semble pas mal du tout
Dernière modification par Masamunai ; 15/03/2010 à 16h31. |
|
|
00
|
|
|
#17 | ||
|
Expert Confirmé Sénior
![]() |
Salut
Voila un code qui reproduit les même résultat que le tien. Par contre un bug apparait a partir de 63 Membres, je m'y pencherais peut être plus tard. Bon teste Code :
a++ Qwaz
__________________
MagicQwaz := Harry Potter la baguette en moins ![]() Le monde dans lequel on vit HammerFest Score PowerBall Gyroscope Green : 11847 |
||
|
|
00
|
|
|
#18 |
|
Invité régulier
![]() Inscription : août 2009 Messages : 140 ![]() |
Oui l'algo de départ était correct:
La simulation envoie simultanément les probas individuelles de chaque chiffre possible "0" "1" ... "8" (la somme de ces probas faisant toujours 100%), ainsi que l'objectif à atteindre SommeCible. Du coup, la somme des probas générées par la macro dans chacune des 2e colonnes de chaque type de Xuplet doit être égale à 100% (si on les génére tous). Cette somme se voit dans la colonne à côté de Nbpermut dans le tableau résultats. Or 1er test que j'ai fait est de taper SommeCible=0, et là tiens: à partir des 4uplets et au delà, la somme de ne fait plus 100% mais 100,0000X% X augmentant régulièrement, donc doit y avoir une combinaison de trop générée par ta macro. En revanche, et surtout quand je commencais à avoir des doutes si tu y arriverais vu que tes posts précédents semblaient avoir zappé la moitié de mes explications, j'avoue je suis baba devant ce bout de code: robuste et rapide semble parfait ![]() Quant au bug pour les 63uplets je peut te rassurer tout de suite : la simulation n'ira jamais jusque là. Personnellement, je pense que cela vient de la limite en colonnes d'Excel2003 (63*3colonnes + la 15zaine du début ~ 210 colonnes déjà). Peut être que je me trompe mais bon ce n'est pas très grave. Je regarderai demain plus en détail comment tu as fait cette perle et jessaierai de trouver la combinaison "en trop". D'ailleurs pour répondre à ta question: NbPermut a un commentaire, il y a aussi une formule dans les cells et au moins 3 posts expliquant qu'on ne génére pas toutes les permutations souhaitées, mais des combinaisons avec répétitions x nb permutations simples à partir de ces combinaisons cette colonne NbPermut me servait surtout à verifier qu'on obtenait bien le bon nombre total souhaité.@ ++ Masa |
|
|
00
|
|
|
#19 |
|
Invité régulier
![]() Inscription : août 2009 Messages : 140 ![]() |
Bonjour,
Bon après avoir passé la matinée à essayer de comprendre la fonction CalculProba, il en ressort pas mal de questions, mais je ne poserai que les principales pour l'instant: 1. Pourquoi faire le contrôle des probas individuelles non nulles dans une boucle à part ? Dans l'algo de départ j'avais réussi à mettre à la fois Tab_vTmp, SomX et sCol dans la même boucle For et le même If, serait pas possible dans ta fonction ? 2. Je crois avoir trouvé d'où proviennent les décimales "en trop" détectées lors du test hier soir: la ligne sCol = sCol * Col(Xx(xDim)), avec Col(Xx(xDim)) et sCol de type Single Au 1er bouclage (xDim=0, pour l'uplet (0;0)), chacun des éléments avant la multiplication contient: Col(Xx(xDim))=0.055 (proba 5.5% pour le chiffre "0") -> OK sCol=1 (suite à l'initialisation à 100%) -> OK puis le résultat de la multiplication, de type single aussi donnera à la boucle suivante : Col(Xx(xDim))=0.055 (proba 5.5% pour le chiffre "0" de nouveau) -> OK sCol=0.055 (résultat boucle précédente) -> OK sCol (Résultat) = 0,00302500000 -> OK ... puis pour l'uplet (0;1) : Col(Xx(xDim))=0.54 (proba 54% pour le chiffre "1") -> OK sCol= 0,055 (résultat boucle précédente) -> OK sCol (Résultat) = 0,0297000017 -> PAS OK ! Résultat après sommation de toutes ces probas multipliées on obtient non pas pile poil 100% mais 100,0000031%. En comparaison, dans l'algo original, cette multiplication se faisait directement, et ne donne pas ces décimales parasites... càd un beau 100% tout rond même en rajoutant 1000 décimales derrière la virgule sont toutes à 0. Ma calculette donne aussi .0297, aucune trace de ce 17 "parasite". En termes de solution pas contre, je vois pas comment régler ça... @++ |
|
|
00
|
|
|
#20 | ||
|
Expert Confirmé Sénior
![]() |
Salut
Citation:
Citation:
Si tu souhaites une telle précision utilise des Double et si tu veux juste un jolie compte rond, arrondi la valeur à 2 ou 3 ou ... ou 6 décimales après la virgule. Normal ici on "arrondi" la valeur de chaque composantes de la multiplication par rapport au type Single, pas ta calculette. Dis moi si les Double corresponde a ton besoin de précision. Une dernière chose par rapport a la précision des calcules, vérifie le nombre de décimales conservé dans une cellule par excel on est très loin du type Double. A++ Qwaz
__________________
MagicQwaz := Harry Potter la baguette en moins ![]() Le monde dans lequel on vit HammerFest Score PowerBall Gyroscope Green : 11847 |
||
|
|
00
|
Copyright © 2000-2012 - www.developpez.com