Défi: optimisation d'une fonction de convertion (Bin => Dec) - VB/VBA/VBS - Programmation
Marsh Posté le 04-01-2005 à 15:08:26
Ensuite on peut voir que tu fait appel plusieurs fois à :
Code :
|
Grosse perte de temps de recalculer la longueur de sBinary, surtout si elle change pas, donc met au début :
Code :
|
Et après remplace tout tes Len(sBinary) par BinaryLen
Marsh Posté le 04-01-2005 à 15:40:15
Ok! J'ai étudié ça. Voici ma nouvelle fonction. je n'utilise plus du tout de len() car ma chaine d'entrée est toujours sur 9 caractères.
Si tu vois comment optimiser cette nouvelle méthode..
Je n'utilise que des longs pour les calculs, j'ai lu dans un tutorial sur l'optimisation que c'était préférable.
je gagne désormais a peu près 25 % de temps d'exécution!
Private Function Bin9BitsToNum(sBinary As String) As Long
Dim nValue As Long
Dim nCpt As Long
Dim nPow As Long
Dim nGet2Pow As Long
nValue = 0
nCpt = 9
While nCpt > 0
If Mid$(sBinary, nCpt, 1) = "1" Then
nPow = 9 - nCpt
nGet2Pow = 2 ^ nPow
nValue = nValue + nGet2Pow
End If
nCpt = nCpt - 1
Wend
BinToNum = nValue
End Function
Marsh Posté le 04-01-2005 à 15:46:31
Tiens pour la comparaison avec "1" :
Code :
|
Sachant que 31 est le code ASCII de "1"
Marsh Posté le 04-01-2005 à 15:49:39
Aussi, tu pourrais précalculer les puissances, vu qu'elles sont connues et limitées. Met un tableau constant dans ton programme qui contient les puissances déjà calculées, afin que tu n'ai que ça à faire :
Code :
|
Marsh Posté le 04-01-2005 à 15:58:08
J'ai encore gagné 5 secondes! (on "bench" en était à 50 sec, j'en suis à 45 juste avec cette modif.
Voici le nouveau code. C'est super ton aide , je pensais pas gagner tout ce temps. Je suis dans mes objectifs maintenant
Private Function Bin9BitsToNum(sBinary As String) As Long
Dim nValue As Long
Dim nCpt As Long
Dim nPow As Byte
Dim nGet2Pow As Long
nValue = 0
nCpt = 9
nPow = 0
While nCpt > 0
If AscW(Mid$(sBinary, nCpt, 1)) = 49 Then
nGet2Pow = 2 ^ nPow
nValue = nValue + nGet2Pow
End If
nPow = nPow + 1
nCpt = nCpt - 1
Wend
Bin9BitsToNum = nValue
End Function
Marsh Posté le 04-01-2005 à 16:00:25
Essaye avec le tableau de puissances. Met une variable globale genre PowerArray = Array(1, 2, 4, 8, 16, 32, 64, 128, 256, 512). Comme ça suffit de faire un PowerArray(nCpt), et hop t'as la puissance cash, pas besoin de la recalculer à chaque fois que tu lances la fonction
Marsh Posté le 04-01-2005 à 16:12:48
Vraiment pas bête!! Ca m'avait même pas effleuré l'esprit les constantes... J'ai encore gagné 4 secondes, j'en suis à 41 secondes pour le bench. Je ne sais pas si on peut faire plus rapide maintenant.
Voici la partie du code de ma classe concernée
private nPowerArray(1 to 9) as long
Private Function Bin9BitsToNum(sBinary As String) As Long
Dim nValue As Long
Dim nCpt As Long
nValue = 0
nCpt = 9
While nCpt > 0
If AscW(Mid$(sBinary, nCpt, 1)) = 49 Then
nValue = nValue + nPowerArray(nCpt)
End If
nCpt = nCpt - 1
Wend
Bin9BitsToNum = nValue
End Function
Private Sub Class_Initialize()
nLevel = 1
nPowerArray(1) = 256
nPowerArray(2) = 128
nPowerArray(3) = 64
nPowerArray(4) = 32
nPowerArray(5) = 16
nPowerArray(6) = 8
nPowerArray(7) = 4
nPowerArray(8) = 2
nPowerArray(9) = 1
End Sub
merci pour tout.
Loïc
Marsh Posté le 04-01-2005 à 16:20:03
Ce qu'il faudrait essayer, c'est de profiler la fonction pour voir quelle est la ligne qui prend le plus de temps
Marsh Posté le 04-01-2005 à 16:25:59
C'est cette ligne qui bouffe le plus :
Code :
|
A voir...
Marsh Posté le 04-01-2005 à 16:26:16
Pour cette fonction ça va aller je pense
Maintenant faut je j'optimise le reste de mon code. Je ne pensais vraiment pas gagner autant de temps avec cette fonction. Tu m'as donné pleins d'idées avec tout ça.
Merci encore.
Marsh Posté le 04-01-2005 à 16:28:55
Oui c'est ce que je me disais Peut être qu'en la décomposant en :
dim cChar as char
cChar = Mid$(sBinary, nCpt, 1)
If AscW(cChar) = 49
J'ai lu qu'en décomposant les calculs on pouvait gagner un peu de temps...
Aller j'essaie!
Marsh Posté le 04-01-2005 à 16:31:06
Et avec ça
Code :
|
c'est moche mais ça doit être très rapide
Marsh Posté le 04-01-2005 à 16:32:07
Ouais, t'as déplié la boucle while C'est sûr plus de décrémentation, ni de condition pour le while, mais après bonjour la syntaxe D'ailleurs ce genre d'optimisation est parfois réalisée par le compilateur...
Marsh Posté le 04-01-2005 à 16:32:50
j'essaie de suite... c vrai que c'est pas beau mais je m'en tape pour cette fonction...
Marsh Posté le 04-01-2005 à 16:33:01
oui mais bon comme on ne sait pas trop comment fonctionne le compilo (ou plutot le pre-compilo) faut tout lui dire...
Marsh Posté le 04-01-2005 à 16:35:29
Mais faudrait remplacer genre
Code :
|
Avec
Code :
|
J'ai pu voir que c'était plus rapide... à vérifier
Marsh Posté le 04-01-2005 à 16:42:00
j'ai des perfs identiques avec
If AscW(Mid$(sBinary, 9, 1)) = 49 Then
nValue = nValue + 1
End If
...
et la fonction sous sa dernière version. Ca doit se jouer au dixième de seconde près maintenant.
Marsh Posté le 04-01-2005 à 16:42:29
une petite question c'est sous quoi (vba , vb.net??) et quelle version du language (ou d'office)
Marsh Posté le 04-01-2005 à 16:44:13
Oui aussi, là j'ai tout fait dans le cas de VB normal, pas VB.NET
Marsh Posté le 04-01-2005 à 16:53:58
par contre en essayant sous excel 2000 (vba), avec la boucle dépliée, ça divise le temps d'execution par 2...
Marsh Posté le 04-01-2005 à 16:54:28
Oui en VBA c'est directement interpreté, en VB normal y'a quand-même une compilation, donc ça doit jouer...
Marsh Posté le 04-01-2005 à 17:23:43
Au lieu de travailler sur une chaîne, il serait peut-être plus judicieux de travailler sur un nombre, en la convertissant (CInt()).
Et aussi, utiliser un masque binaire, au lieu d'une égalité.
Marsh Posté le 04-01-2005 à 17:31:07
Et un petit :
Code :
|
à la place du while proposé, ça n'irait pas ?
Marsh Posté le 04-01-2005 à 17:31:55
Bah je ne suis pas sur qu'en rajoutant une conversion en entier on y gagne car finalement on va faire string vers int(binaire) vers int au lieu de faire directement string vers int
Marsh Posté le 04-01-2005 à 17:48:18
dreameddeath a écrit : Bah je ne suis pas sur qu'en rajoutant une conversion en entier on y gagne car finalement on va faire string vers int(binaire) vers int au lieu de faire directement string vers int |
Je propose :
Code :
|
Au lieu de :
Code :
|
Marsh Posté le 04-01-2005 à 18:11:35
Est-ce que le Cint va fonctionner ? J'me demande s'il va pas faire un erreur...
Marsh Posté le 04-01-2005 à 18:15:12
FlorentG a écrit : Est-ce que le Cint va fonctionner ? J'me demande s'il va pas faire un erreur... |
J'ai testé.
Marsh Posté le 04-01-2005 à 18:18:48
FlorentG a écrit : Est-ce que le Cint va fonctionner ? J'me demande s'il va pas faire un erreur... |
Utilise CLng, tu auras un dépassement de capacité avec CInt.
Marsh Posté le 04-01-2005 à 18:20:20
charly007 a écrit : J'ai testé. |
Ok
Ben si ça marche, c'est sûr qu'il y ait moyen que ce soit plus rapide
Marsh Posté le 04-01-2005 à 18:25:02
mareek a écrit : Utilise CLng, tu auras un dépassement de capacité avec CInt. |
CInt(expression)
Plage de valeurs de l'argument expression :
-2 147 483 648 à 2 147 483 647
Je pense que ça ira A moins qu'il en soit différemment dans sa version de VB.
Marsh Posté le 04-01-2005 à 18:47:38
charly007 a écrit : CInt(expression) |
perdu
Citation : CInt Integer -32,768 to 32,767; fractions are rounded. |
http://msdn.microsoft.com/library/ [...] ersion.asp
Marsh Posté le 04-01-2005 à 18:50:34
mareek a écrit : perdu
|
Citation : |
Moi ce que j'ai donné c'est du VB.NET.
Et puis, c'est un détail minime.
Marsh Posté le 04-01-2005 à 19:02:18
il a dit que c'était du VB6
Marsh Posté le 04-01-2005 à 19:03:33
donc c'est pas du VBA comme le liens que tu donnes dans VB l'integer c'est du 32 bits (soit environ 4 milliard de valeurs possibles)
Marsh Posté le 04-01-2005 à 14:38:09
Salut!
J'ai besoin dans un programme d'avoir une fonction qui me converti en nombre entier une chaine de caractères représentative d'un nombre binaire strictement positif compris entre 0 et 511 ex: "100110100" (codage sur 9 bits).
Cette fonction doit être appelée environ 9 000 000 de fois à la suite. Il me faut donc qu'elle soit le plus rapide possible. Je poste la fonction que je me suis programmé mais que je voudrais optimiser.
Si vous avez des idée pour augmenter la rapidité du code je vous serai reconnaissant.
Merci!
Loïc
<code>
Private Function BinToNum(sBinary As String) As Long
Dim nValue As Long
Dim nCpt As Long
Dim nPow As Byte
nValue = 0
nCpt = 1
While nCpt <= Len(sBinary)
If Mid$(sBinary, nCpt, 1) = "1" Then
nPow = Len(sBinary) - nCpt
nValue = nValue + (2 ^ nPow)
End If
nCpt = nCpt + 1
Wend
BinToNum = nValue
End Function
</code>
Message édité par LCPROG le 04-01-2005 à 15:06:42