Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2292 connectés 

  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  Défi: optimisation d'une fonction de convertion (Bin => Dec)

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Précédente
Auteur Sujet :

Défi: optimisation d'une fonction de convertion (Bin => Dec)

n°936651
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 14:38:09  profilanswer
 

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
mood
Publicité
Posté le 04-01-2005 à 14:38:09  profilanswer
 

n°936668
FlorentG
Unité de Masse
Posté le 04-01-2005 à 14:49:48  profilanswer
 

Déjà remplace Mid par Mid$

n°936704
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 15:06:15  profilanswer
 

effectivement! je gagne déjà 15% de temps
 
Merci bien.

n°936709
FlorentG
Unité de Masse
Posté le 04-01-2005 à 15:08:26  profilanswer
 

Ensuite on peut voir que tu fait appel plusieurs fois à :

Code :
  1. Len(sBinary)


Grosse perte de temps de recalculer la longueur de sBinary, surtout si elle change pas, donc met au début :

Code :
  1. Dim BinaryLen as Integer = Len(sBinary)


Et après remplace tout tes Len(sBinary) par BinaryLen

n°936753
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 15:40:15  profilanswer
 

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


Message édité par LCPROG le 04-01-2005 à 15:40:43
n°936762
FlorentG
Unité de Masse
Posté le 04-01-2005 à 15:46:31  profilanswer
 

Tiens pour la comparaison avec "1" :

Code :
  1. If AscW(Mid$(sBinary, nCpt)) = 31 Then
  2. ...


Sachant que 31 est le code ASCII de "1"

n°936769
FlorentG
Unité de Masse
Posté le 04-01-2005 à 15:49:39  profilanswer
 

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 :
  1. nValue = PowerArray(nCpt)

n°936793
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 15:58:08  profilanswer
 

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

n°936803
FlorentG
Unité de Masse
Posté le 04-01-2005 à 16:00:25  profilanswer
 

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

n°936832
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 16:12:48  profilanswer
 

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

mood
Publicité
Posté le 04-01-2005 à 16:12:48  profilanswer
 

n°936842
FlorentG
Unité de Masse
Posté le 04-01-2005 à 16:20:03  profilanswer
 

Ce qu'il faudrait essayer, c'est de profiler la fonction pour voir quelle est la ligne qui prend le plus de temps :)

n°936850
FlorentG
Unité de Masse
Posté le 04-01-2005 à 16:25:59  profilanswer
 

C'est cette ligne qui bouffe le plus :

Code :
  1. If AscW(Mid$(sBinary, nCpt, 1)) = 49


A voir... :)

n°936851
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 16:26:16  profilanswer
 

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.
 

n°936856
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 16:28:55  profilanswer
 

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!

n°936860
dreameddea​th
Posté le 04-01-2005 à 16:31:06  profilanswer
 

Et avec ça :)
 

Code :
  1. res = 0
  2. If Mid$(sBin, 1, 1) = "1" Then
  3.    res = res + 256
  4. End If
  5. If Mid$(sBin, 2, 1) = "1" Then
  6.    res = res + 128
  7. End If
  8. If Mid$(sBin, 3, 1) = "1" Then
  9.    res = res + 64
  10. End If
  11. If Mid$(sBin, 4, 1) = "1" Then
  12.    res = res + 32
  13. End If
  14. If Mid$(sBin, 5, 1) = "1" Then
  15.    res = res + 16
  16. End If
  17. If Mid$(sBin, 6, 1) = "1" Then
  18.    res = res + 8
  19. End If
  20. If Mid$(sBin, 7, 1) = "1" Then
  21.    res = res + 4
  22. End If
  23. If Mid$(sBin, 8, 1) = "1" Then
  24.    res = res + 2
  25. End If
  26. If Mid$(sBin, 9, 1) = "1" Then
  27.    res = res + 1
  28. End If


c'est moche mais ça doit être très rapide

n°936865
FlorentG
Unité de Masse
Posté le 04-01-2005 à 16:32:07  profilanswer
 

Ouais, t'as déplié la boucle while :D 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...


Message édité par FlorentG le 04-01-2005 à 16:32:23
n°936868
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 16:32:50  profilanswer
 

j'essaie de suite... c vrai que c'est pas beau mais je m'en tape pour cette fonction...

n°936869
dreameddea​th
Posté le 04-01-2005 à 16:33:01  profilanswer
 

oui mais bon comme on ne sait pas trop comment fonctionne le compilo (ou plutot le pre-compilo) faut tout lui dire...

n°936871
FlorentG
Unité de Masse
Posté le 04-01-2005 à 16:35:29  profilanswer
 

Mais faudrait remplacer genre  

Code :
  1. If Mid$(sBin, 9, 1) = "1" Then
  2.    res = res + 1
  3. End If


Avec

Code :
  1. If AscW(Mid$(sBin, 9, 1)) = 49 Then
  2.   res = res + 1
  3. End If


J'ai pu voir que c'était plus rapide... à vérifier

n°936875
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 16:36:28  profilanswer
 

ça passe à 48 secondes avec ça, c'est pas plus rapide

n°936877
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 16:37:08  profilanswer
 

J'essaie avec le second code...

n°936886
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 16:42:00  profilanswer
 

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.

n°936887
dreameddea​th
Posté le 04-01-2005 à 16:42:29  profilanswer
 

une petite question c'est sous quoi (vba , vb.net??) et quelle version du language (ou d'office)

n°936891
FlorentG
Unité de Masse
Posté le 04-01-2005 à 16:44:13  profilanswer
 

Oui aussi, là j'ai tout fait dans le cas de VB normal, pas VB.NET

n°936894
LCPROG
Bande d'Ours
Posté le 04-01-2005 à 16:46:48  profilanswer
 

c'est sous vb sp6 :)

n°936906
dreameddea​th
Posté le 04-01-2005 à 16:53:58  profilanswer
 

par contre en essayant sous excel 2000 (vba), avec la boucle dépliée, ça divise le temps d'execution par 2...

n°936907
FlorentG
Unité de Masse
Posté le 04-01-2005 à 16:54:28  profilanswer
 

Oui en VBA c'est directement interpreté, en VB normal y'a quand-même une compilation, donc ça doit jouer...

n°936980
charly007
Posté le 04-01-2005 à 17:23:43  profilanswer
 

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


Message édité par charly007 le 04-01-2005 à 17:32:13
n°936998
dsls
Posté le 04-01-2005 à 17:31:07  profilanswer
 

Et un petit :

Code :
  1. While nCpt <= Len(sBinary)
  2.        nValue = 2*nValue
  3.        If Mid$(sBinary, nCpt, 1) = "1" Then
  4.           nValue = nValue + 1
  5.        End If
  6.        nCpt = nCpt + 1
  7.    Wend


à la place du while proposé, ça n'irait pas ?

n°937000
dreameddea​th
Posté le 04-01-2005 à 17:31:55  profilanswer
 

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

n°937028
charly007
Posté le 04-01-2005 à 17:48:18  profilanswer
 

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 :
  1. valeur = CInt(sBinary)
  2. If (valeur And 256) Then


Au lieu de :

Code :
  1. If AscW(Mid$(sBin, 9, 1)) = 49 Then


Message édité par charly007 le 04-01-2005 à 17:48:40
n°937070
FlorentG
Unité de Masse
Posté le 04-01-2005 à 18:11:35  profilanswer
 

Est-ce que le Cint va fonctionner ? J'me demande s'il va pas faire un erreur...

n°937074
charly007
Posté le 04-01-2005 à 18:15:12  profilanswer
 

FlorentG a écrit :

Est-ce que le Cint va fonctionner ? J'me demande s'il va pas faire un erreur...


J'ai testé.

n°937081
mareek
Et de 3 \o/
Posté le 04-01-2005 à 18:18:48  profilanswer
 

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.


---------------
"I wonder if the internal negative pressure in self pumping toothpaste tubes is adjusted for different market altitudes." John Carmack
n°937084
FlorentG
Unité de Masse
Posté le 04-01-2005 à 18:20:20  profilanswer
 


 
Ok :jap:
 
Ben si ça marche, c'est sûr qu'il y ait moyen que ce soit plus rapide :D

n°937087
charly007
Posté le 04-01-2005 à 18:25:02  profilanswer
 

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.


Message édité par charly007 le 04-01-2005 à 18:27:54
n°937127
mareek
Et de 3 \o/
Posté le 04-01-2005 à 18:47:38  profilanswer
 

charly007 a écrit :

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.


perdu

Citation :

CInt          Integer           -32,768 to 32,767; fractions are rounded.


http://msdn.microsoft.com/library/ [...] ersion.asp


---------------
"I wonder if the internal negative pressure in self pumping toothpaste tubes is adjusted for different market altitudes." John Carmack
n°937129
charly007
Posté le 04-01-2005 à 18:50:34  profilanswer
 

mareek a écrit :

perdu

Citation :

CInt          Integer           -32,768 to 32,767; fractions are rounded.


http://msdn.microsoft.com/library/ [...] ersion.asp


Citation :


Visual Basic for Applications Reference


Moi ce que j'ai donné c'est du VB.NET.
Et puis, c'est un détail minime. :D


Message édité par charly007 le 04-01-2005 à 18:52:03
n°937152
mareek
Et de 3 \o/
Posté le 04-01-2005 à 19:02:18  profilanswer
 

il a dit que c'était du VB6 ;)


---------------
"I wonder if the internal negative pressure in self pumping toothpaste tubes is adjusted for different market altitudes." John Carmack
n°937153
dreameddea​th
Posté le 04-01-2005 à 19:03:33  profilanswer
 

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)

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  Défi: optimisation d'une fonction de convertion (Bin => Dec)

 

Sujets relatifs
[C] Convertion double -> dec -> hexComment faire pour qu'une fonction renvoie un tableau?
executer un scrpt en fonction de l'ip de l'userFonction asm utilisable en C++, linker error...
[Maple] cherche une fonction qui retourne la taille d'une tableSocket : la fonction connect.
help: probleme de fonction .h en Cbesoin d'aide pour convertion html-->css
Question à propos d'une fonction du htacces de PHPNuke 
Plus de sujets relatifs à : Défi: optimisation d'une fonction de convertion (Bin => Dec)


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR