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

Python Discussion :

Optimisation code pour "flottant"


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2009
    Messages
    197
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 197
    Par défaut Optimisation code pour "flottant"
    Bonjour à tous,

    je parviens à récupérer les données d'une ancienne base de données via python et un éditeur hexadecimal.

    La representation des flottants dans cette base est assez particuliere..
    Dans l'editeur hexadecimal, j'ai ceci pour les nombres :

    30 : 41 30 00 00 00 00 00 00
    1 : 40 10 00 00 00 00 00 00
    1.5 : 40 15 00 00 00 00 00 00
    -2 : C0 20 00 00 00 00 00 00

    Le premier octet sert à déterminer la virgule et le signe
    Si sa valeur (décimale) est supérieur à 128 alors le nombre est négatif

    J'ai réalisé cette fonction pour obtenir le nombre décodé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    	def readFlt(self,rec) :
    		flt , b , expo , sgn = '' , ord(rec[0:1]) , 64 , 1
    		rec=rec[1:]
    		if b > 128 : expo , sgn = 192 , -1
    		for i in range(7) :	flt += ('0' + (hex(ord(rec[i:i+1])) [2:]))[-2:]
    		flt = str(int(flt[::-1]))[::-1].strip() 
    		if Decimal(flt) == 0 : return '0.0'
    		return str(sgn * Decimal(flt) * 10 ** Decimal(str(b - (expo + len(flt) - 1))  ) )
    Ca fonctionne bien mais c'est assez lent lorsque je fais des milliers de lectures des enregistrements.
    Je remarque que c'est cette fonction qui prend énormément de temps.
    Y a t il une façon (des façons) d'optimiser ceci?

    Merci

  2. #2
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Salut,

    Difficile de tester, en tout cas de recréer les valeurs que tu as.

    ord("x") n'accepte qu'un seul caractère, donc pas "00", ni non plus une liste, or tu utilises rec[0:1] ce qui retourne non pas le premier élément, mais une liste contenant ce premier élément.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    >>> lst = ["40", "00", "10"]
    >>> lst[0]
    '40'
    >>> lst[0:1]
    ['40']
    Donc, manifestement, tes données contenues dans 'rec' sont sous une autre forme qu'une liste.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2009
    Messages
    197
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 197
    Par défaut
    rec contient les données brutes.
    rec[0:1] contient le 1er octet

    je me rends compte que ma boucle for ne sert à rien..
    On a l'équivalent avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    flt = rec[:7].encode('hex')
    ensuite j'inverse 2 fois cette chaine obtenue pour ôter les '0' à droite
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    flt = str(int(flt[::-1]))[::-1].strip()
    bizarrement, c'est + rapide comme ca qu'avec flt.rstrip('0')

    Je sais pas si on peut vraiment optimiser cette affaire là de plus...

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 25
    Par défaut
    si tu veux un code rapide, le mieux est de coder ta fonction en c puis de l'importer dans ton code python.
    alors ne me demande pas comment implémenter ta fonction en C, je ne connais pas asse le c pour ça, mais ce qui est sur c'est que l’intégration d'une lib écrite en c dans python est très simple.

    donc si tu gère le c, cherche aussi dans ce sens

  5. #5
    Membre Expert

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Par défaut
    Quand je lis*:

    Citation Envoyé par Nico_tournai Voir le message
    30 : 41 30 00 00 00 00 00 00
    1 : 40 10 00 00 00 00 00 00
    1.5 : 40 15 00 00 00 00 00 00
    -2 : C0 20 00 00 00 00 00 00
    Je me dis qu’il y a un problème… Si ce sont des représentations hexadécimales d’octet, 30 vaut 48 en décimal… Es-tu sûr de toi dans la description du format*?

  6. #6
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Citation Envoyé par mont29 Voir le message
    Je me dis qu’il y a un problème… Si ce sont des représentations hexadécimales d’octet, 30 vaut 48 en décimal… Es-tu sûr de toi dans la description du format*?
    On dirait que la mantisse est codée en "packed BCD".

    Je ne sais pas si ce sera plus rapide, mais tu peux essayer qqch comme ceci:
    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
    from ctypes import Structure, c_uint
     
    class MyFloat(Structure):
        _fields_ = [("expo", c_uint, 7),
                    ("sign", c_uint, 1),
                    ("m2", c_uint, 4),
                    ("m1", c_uint, 4),
                    ("m4", c_uint, 4),
                    ("m3", c_uint, 4),
                    ("m6", c_uint, 4),
                    ("m5", c_uint, 4),
                    ("m8", c_uint, 4),
                    ("m7", c_uint, 4),
                    ("m10", c_uint, 4),
                    ("m9", c_uint, 4),
                    ("m12", c_uint, 4),
                    ("m11", c_uint, 4),
                    ("m14", c_uint, 4),
                    ("m13", c_uint, 4)]
     
    def read_flt(rec):
        f = MyFloat.from_buffer_copy(rec)
        m = reduce(lambda acc,x: x + acc/10.0, (f.m14,f.m13,f.m12,f.m11,f.m10,f.m9,f.m8,
                                                f.m7,f.m6,f.m5,f.m4,f.m3,f.m2,f.m1))
        return (1 - 2 * f.sign) * m * 10 ** (f.expo-64)
     
    tests = ['\x41\x30\x00\x00\x00\x00\x00\x00',
             '\x40\x10\x00\x00\x00\x00\x00\x00',
             '\x40\x15\x00\x00\x00\x00\x00\x00',
             '\xC0\x20\x00\x00\x00\x00\x00\x00']
     
    for t in tests:
        print read_flt(t)

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2009
    Messages
    197
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 197
    Par défaut
    SUPER!

    J'ai pas tout compris mais c'est bien + rapide que mon 1er code!
    Oui la valeur en hexa de mon nombre correspond à la valeur décimale.

    J'ai du installer python 2.7 pour que ton code fonctionne (j'avais la 2.5)

    J'avais fait de mon côté une fonction qui est un peu + rapide que la tienne sur des milliers de lectures.
    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
     
    	def readFlt(self,rec) :
    		if ord(rec[0:1]) == 0 : return '0.0'
    		b , expo , sgn = ord(rec[0:1]) , 64 , ''
    		if b > 128 : expo , sgn = 192 , '-'
    		flt = rec[1:8].encode('hex')
    		flt = str(int(flt[::-1]))[::-1] #.strip() 
    		l = len(flt)
    		mant = b - (expo + l - 1)
    		if mant > 0 :
    			flt = flt.ljust(l+mant,'0')
    		elif mant < 0:
    			flt = flt.rjust(l-mant,'0')
    			flt = str(int(flt[:mant]))+'.'+flt[mant:]
    		return sgn + flt
    Peut être que là il y a moyen d'optimiser encore un peu mais c'est déjà pas mal

    merci beaucoup pour ton aide, je connaissais pas cette forme d'encodage de flottant

Discussions similaires

  1. Optimisation code pour gagner en rapidité
    Par polodu84 dans le forum MATLAB
    Réponses: 2
    Dernier message: 05/03/2008, 15h32

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