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 :

Float arrondi à n décimales


Sujet :

Python

  1. #1
    Membre confirmé
    Inscrit en
    Août 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 64
    Par défaut Float arrondi à n décimales
    Bonjour,
    Je souhaite afficher un variable float avec n décimales en toute circonstance.
    Je connais la fonction round. Elle a le désavantage de couper des éventuels zéros finals:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    round(1.0/10.0,3) -> 0.1 mais je veux 0.100
    J'avais pensé autrefois (cf ancien post) à passer en string et ne conserver que les premières positions, mais là il n'y a plus d'arrondi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str(pi)[:5] -> 3.141 mais il faut 3.142
    Evidemment quelqu'un me dira qu'en faisant:
    on obtient le bon résulat, mais le problème des zéros ci-dessus demeure:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str(round(1.0/10.0,0.3))[:5] -> 0.1 et pas 0.100
    Quelqu'un a-t-il une idée? J'aimerais éviter quand même un truc du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    while len(str(a))<6:
    str(a)+='0'
    qui est bien torcheculatif...
    Merci.

  2. #2
    Membre confirmé Avatar de moumine
    Profil pro
    Étudiant
    Inscrit en
    Août 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2008
    Messages : 237
    Par défaut
    Salut,

    Ce que j'utlilse:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    x = int(x*1000)
    x = (float(x))/1000
    Voila, c'est ma façon de faire, je sais bien que c'est pas précis mais je pense que sa doit pas poser de problème dans ton cas.
    x = la valeur que tu veux simplifier
    1000 = le nombre de chiffre après la virgule (donc 3)

    A+

  3. #3
    Membre confirmé
    Inscrit en
    Août 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 64
    Par défaut
    Je dois être bobet, mais chez moi ça ne marche pas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> a = 10.21
    >>> a = int(a*1000)
    >>> a
    10210
    >>> a = float(a)/1000
    >>> a
    10.210000000000001
    >>> str(a)
    '10.21'
    En tout cas, j'ai toujours un affichage de 10.21 et pas 10.210...

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Il vaut mieux utiliser les fonctions de formatage avec %:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    print "%.4f" % 3.3333333333
    3.3333
    print "%.4f" % 6.6666666666
    6.6667
    Tyrtamos

    Edit: et, bien sûr:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    print "%.4f" % 0.1
    0.1000

  5. #5
    Membre confirmé
    Inscrit en
    Août 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 64
    Par défaut
    OK lorsqu'il faut utiliser print,. Dans mon cas la valeur est mise dans une variable, d'où l'idée de passer par un string qui conserve les zéros finals.

    ps-ceux qui utilisent des strings sont souvent sur la corde raide!

  6. #6
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Ce n'est pas propre à print, ça fabrique du string:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    x="%.4f" % 0.1
     
    print type(x)
    <type 'str'>
     
    print x
    0.1000
    Tyrtamos

  7. #7
    Membre confirmé Avatar de moumine
    Profil pro
    Étudiant
    Inscrit en
    Août 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2008
    Messages : 237
    Par défaut
    Salut,

    Je sais pas ce qui ce passe, normalement sa devrait fonctionner.
    Mais le plus bizzare c'est que tu obtient:
    alors que tu es censé avoir:
    es-tu sur d'avoir fait sa :

    moi j'ai plutot l'impression que tu as fait sa:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    a = float((a)/1000) #les parenthése orange son théorique pour expliquer ce que l'intérpréteur a fait (enfin c'est ce que je pense)
    A+

  8. #8
    Membre confirmé
    Inscrit en
    Août 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 64
    Par défaut
    Et ben voilà, c'est exactement ce que je cherchais!
    Merci beaucoup.

  9. #9
    Membre confirmé Avatar de moumine
    Profil pro
    Étudiant
    Inscrit en
    Août 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2008
    Messages : 237
    Par défaut
    Euh juste c'est qui que tu remercie ??
    C'est qui qui a la bonne version ?

  10. #10
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut Perso je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x = str(a) +(6-len(str(a))*'0'

  11. #11
    Membre confirmé Avatar de moumine
    Profil pro
    Étudiant
    Inscrit en
    Août 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2008
    Messages : 237
    Par défaut
    Normalement sa doit étre juste ce que j'ai posté non ??
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    x = int(x*1000)
    x = (float(x))/1000
    Quelqun pourrait tester sa, parce que j'ai pas python sous la main et je suis au boulot.
    Et sa me fait stresser que "frites.saucisse" me dise que sa marche pas .

    A+

  12. #12
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Pour moumine:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    x=0.1
    x = int(x*1000)
    x = (float(x))/1000
    print x
    0.1

  13. #13
    Membre confirmé
    Inscrit en
    Août 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 64
    Par défaut
    Bin j'ai déjà testé ton bout de code dans une console (message 3) et ça donne le résultat que j'ai indiqué (j'ai bien mis les parenthèses au bon endroit).

    De ce que je comprends, c'est normal, puisqu'aucun format n'est donné à cet affichage (autant pour le float que pour le str). En revanche lorsque tu fais comme tyrtamos le dit, là les zéros finals restent puisque tu transformes le float en string et que tu lui assignes un format d'affichage.

  14. #14
    Membre confirmé Avatar de moumine
    Profil pro
    Étudiant
    Inscrit en
    Août 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2008
    Messages : 237
    Par défaut
    Pourtant j'était sur que sa fonctionne...
    désolé pour cette erreur
    Question débile: pour quelle raison tu veux afficher ces zéros ?
    A+

  15. #15
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    Salut, pourquoi ne pas créer une classe qui servirai à représenter des float... je veux dire sous frome de fraction. Par exemple 0.12=12/100
    J'ai vite fais un exemple du genre de classe à laquelle je pensais, mais il te restera pas mal de méthode spéciales à définir : celles des opérations, et de comparaison, direction les docs sur l'émulation numérique et la customisation basique.

    L'ébauche de classe
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    >>> class Float(object):
     __slots__=('mult','val')
     def __init__(self,value=0.0,mult=None):
      if type(value)not in (float,int): raise
      if mult==None:
       if type(value)==float:
        self.mult=10**len(str(value).split('.')[-1])
        self.val=int(str(value).replace('.',''))
       else:
        self.mult=0
        self.val=value
      else:
       if mult%10!=0 or type(value)!=int:raise
       self.mult=mult
       self.val=value
     
     def __repr__(self): return '( %i / %i ) <Float>'%(self.val,self.mult)
     
     def __add__(self,other): #methode spéciale appelée lors d'une addition
      if type(other)==int:
       return Float(self.val+other*self.mult,self.mult)
      elif other.__class__==Float().__class__:
       if other.mult>self.mult:
        m=other.mult/self.mult
        mu=self.mult*m
        va=self.val*m
        return Float(va+other.val,mu)
       elif other.mult<self.mult:
        m=self.mult/other.mult
        mu,va=other.mult*m,other.val*m
        return Float(va+self.val,mu)
       elif other.mult==self.mult:
        return Float(self.val+other.val,self.mult)
     
     def round(self,integer): #definition d'une méthode pour arrondir à n décimales
      if type(integer)!=int and interger > len(str(self.val)): raise
      mult=int(str(self.mult)[:integer+1])
      entier=str(self.val)[:str(self.mult).count('0')*-1]
      _float=str(self.val)[str(self.mult).count('0')*-1:]
      if 10-int(_float[integer])>5:
       val=_float[:integer]
      else:
       val=str(int(_float[:integer])+1)
       if len(val)>integer:
        entier,val=str(int(entier)+1),val[1:]
      return Float(int(entier+val),mult)
     
     def n_dec(self,integer): #méthode pour demander l'adaptation de la fraction, à n décimales
      if type(integer)!=int: raise
      if integer<len(str(self.mult))-1:
       return self.round(integer)
      elif integer>len(str(self.mult))-1:
       add='0'*(integer-(len(str(self.mult))-1))
       mult=str(self.mult)+add
       val=str(self.val)+add
       return Float(int(val),int(mult))
      else: return Float(self.val,self.mult)
     
     def __str__(self): #méthode spéciale appelée lors d'une tentative de convertion de l'objet en string
      l=len(str(self.mult))-1
      val=str(self.val)[:l*-1]+'.'+str(self.val)[l*-1:]
      if val[0]=='.': val='0'+val
      return val
    Exemple du résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> a=Float(0.9856)
    >>> a.n_dec(2)
    ( 99 / 100 ) <Float>
    >>> a.n_dec(6)
    ( 985600 / 1000000 ) <Float>
    >>> str(a.n_dec(6))
    '0.985600'
    >>> a.n_dec(2)+1
    ( 199 / 100 ) <Float>
    La classe est chiante à définir, mais une fois que c'est fait, on peut s'en servir facilement, dis-toi juste qu'il ne faudras pas dans la suite du code de servir de float mais de Float et de convertir si besoin est. l'avantage de cette classe (une fois l'émulation numérique faite), c'est qu'elle supportera les opérations +,-,/ etc... alors même si visuellement pour l'utilisateur ça peut être déstabilisant, l'ordinateur lui s'y retrouvera très bien, et lorsque l'utilisateur à besoin d'un affichage sur l'écrant du Float, une petite méthode str(x) et c'est op!

  16. #16
    Membre confirmé
    Inscrit en
    Août 2007
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 64
    Par défaut
    @ N.tox
    J'avais pensé à un truc du style, par un nouveau Float, mais à un nouveau Round. Je l'ai abandonné
    1- car je ne voulais pas avoir deux lignes d'appel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    a=Round(...)
    a.nbre_decimales(2)
    2- car je n'ai pas réussi à programmer un Round(expression,nbre_décimales)
    3- car la solution en "%.4f" fait exactement ce que je veux.
    Bon si quelqu'un sait faire la fonction Round(), je suis toujours intéressé.

    @ Moumine
    Question d'esthétique...

  17. #17
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Round = lambda x, n: eval('"%.' + str(int(n)) + 'f" % ' + repr(x))
     
    print Round(0.1, 2)
    0.10
    print Round(0.1, 4)
    0.1000
    print Round(0.1, 10)
    0.1000000000
    Tyrtamos

  18. #18
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    La solution de Tyrtamos est courte, simple, légère efficace , mais peut se révéler assez embêtante suivant ce que l'on veut faire : par exemple stocker le resultat du Round() dans une variable et plus tard ajouter un int ou un float à cette dernière.

    Donc, suivant les conditions d'utilisation de l'effet recherché et les manipulations devant être éffectuée sur ce dernier, la longueur du code, et le nombre de fois ou l'on sera ammener à manipuler le résultat de l'une ou l'autre soluce, l'une sera plus adaptée que l'autre ou vice et versa...

    L'ébauche de ce que je t'avais proposé m'a ammusé, et je l'ai développer et un peu amélioré, il reste sans nul doute des optimisations à effectuer... J'ai rajouter aussi un paramètre 'dec' dans la définition de __init__(), avec comme valeur par défaut None, si ce paramètre prend une valeur >0, alors les résultats seront toujours arrondis a n décimales... Dans le cas d'une addition de deux objets Float avec des valeurs différentes pour ce paramètre, alors dec prendra la valeur de l'objet à gauche de l'opérateur... enfin bref je me suis bien ammusé, maintenant, va falloir que j'attaques les optimisations ...

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    class Float(object):
        __slots__=('mult','val','sf','dec')
        def __init__(self,value=0.0,mult=None,sf=None,d=None):
            if type(value)not in (float,int): raise
            if mult==None:
                if type(value)==float:
                    if 'e-' in str(value):
                        self.mult=int('1'+'0'*(int(str(value).split('e-')[-1])+len(str(value).split('e-')[0].split('.')[-1])))
                        self.val=int(str(value).split('e-')[0].replace('.',''))
                    else:
                        self.mult=10**len(str(value).split('.')[-1])
                        self.val=int(str(value).replace('.',''))
                else:
                    self.mult=1
                    self.val=value
            else:
                if mult!= 1 and mult%10!=0 or type(value)!=int:raise
                self.mult=mult
                self.val=value
            if sf==None:
                if self.val<0:
                    self.sf=1
                    self.val=abs(self.val)
                else: self.sf=0
            else:
                if self.val<0:
                    self.sf=1
                    self.val=abs(self.val)
                else: self.sf=sf
            self.dec=d if type(d)==int and d >0 else None
        def __repr__(self):
            return '%s( %i / %s )<Float>'%('-' if self.sf==1 else '+',self.val,'1e'+str(str(self.mult).count('0')))
        def __add__(self,other):
            if type(other)!=float:
                other=float(other)
            val=float(self)+other
            return Float(val,d=self.dec)
        def __radd__(self,other):
            return other.__add__(self)
        def __sub__(self,other):
            if type(other)!=float:
                other=float(other)
            val=float(self)-other
            return Float(val,d=self.dec)
        def __rsub__(self,other):
            if type(other)!=float:
                other=float(other)
            return other.__sub__(self)
        def __mul__(self, other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                sf=self.sf^other.sf
                val=self.val*other.val
                mu=self.mult*other.mult
                return Float(val,mu,sf,d=self.dec)
            else: raise
        def __rmul__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            return other.__mul__(self)
     
        def __floordiv__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                sf=self.sf^other.sf
                val=(self.val*other.mult)/(other.val*self.mult)
                return Float(val,sf=sf,d=self.dec)
            else: raise
        def __div__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                sf=self.sf^other.sf
                val=(float(self.val)*other.mult)/(other.val*self.mult)
                return Float(val,sf=sf,d=self.dec)
            else:raise
        def __truediv__(self,other):
            return self.__div__(other)
        def __rdiv__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                return other.__div__(self)
            else:raise
     
        def __mod__(self,other):
            val=float(self.__str__())%(float(other.__str__()) if other.__class__==Float().__class__ else other)
            return Float(val,d=self.dec)
        def __rmod__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            return other.__mod__(Float(self.val,self.mult,self.sf))
     
        def __divmod__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            return (self.__floordiv__(other),self.__mod__(other))
        def __rdivmod__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            return (other.__floordiv__(self),other.__mod__(self))
     
        def __pow__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                return Float(float(self)**float(other),d=self.dec)
        def __rpow__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                return Float(float(other)**float(self),d=other.dec)
     
        def round(self,integer):
            val=('-'if self.sf==1 else '')+str(float(self.val)/self.mult)
            if '-' in val: val=val.replace('-','')
            if 'e' not in val:
                entier=val.split('.')[0]
                _float=val.split('.')[1]
            else:
                entier='0'
                _float,dec=val.split('e')[0],int(val.split('e')[-1])
                _float=_float.split('.')[0].rjust(dec,'0')+_float.split('.')[-1]
     
            if 10-int(_float[integer])>5:
                val=_float[:integer]
            else:
                val=str(int(_float[:integer])+1)
                if len(val)>integer:
                    entier,val=str(int(entier)+1),val[1:]
            mult=int('1'+'0'*integer)
     
            return Float(int(entier+val),mult,self.sf)
        def n_dec(self,integer):
            if type(integer)!=int: raise
            if integer<str(self.mult).count('0'):
                return self.round(integer)
            elif integer>str(self.mult).count('0'):
                add='0'*(integer-str(self.mult).count('0'))
                mult=str(self.mult)+add
                val=str(self.val)+add
                return Float(int(val),int(mult),self.sf)
            else: return Float(self.val,self.mult,self.sf)
        def __str__(self):
            r=self.n_dec(self.dec)if self.dec!=None else self
            dec=str(r.mult).count('0')
            val=str(r.val)
            if len(val)<= dec:
                if dec-len(val)>8:
                    val=('-' if r.sf==1 else '')+val[0]+'.'+val[1:]+'e-'+str((dec-len(val[1:])))
                else:
                    val=('-' if r.sf==1 else '')+'0.'+val.rjust(dec,'0')
            else:
                val=('-' if self.sf==1 else '')+(val[:dec*-1]+'.'+val[dec*-1:] if dec!=0 else val)
            return val
     
        def __nonzero__(self):
            return (self.sf==1 and [0] or [1])[0]
     
        def __float__(self):
            return float(self.__str__())
        def __int__(self):
            return int(self.__float__())
        def __long__(self):
            return long(self.__float__())
        def __complex__(self):
            return complex(self.__float__())
     
        def __neg__(self):
            return Float(self.val,self.mult,(1 if self.sf==0 else 0))
        def __pos__(self):
            return self
        def __abs__(self):
            return Float(self.val,self.mult)
     
        def __gt__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                return True if self.__float__()>other.__float__() else False
        def __ge__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                return True if self.__float__()>=other.__float__() else False
        def __eq__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                return True if self.__float__()==other.__float__() else False
        def __ne__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                return True if self.__float__()!=other.__float__() else False
        def __lt__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                return True if self.__float__()<other.__float__() else False
        def __le__(self,other):
            if type(other) in (float,int):
                other=Float(other)
            if other.__class__==Float().__class__:
                return True if self.__float__()<=other.__float__() else False
    là un exemple du résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> a=Float(-5.888,d=2)
    >>> print 'a=Float(-5.888,d=2) =',a
    a=Float(-5.888,d=2) = -5.89
    >>> print 'a+9.768513+0.00016549 =',a+9.768513+0.00016549
    a+9.768513+0.00016549 = 3.88
    Voilà voilà...

    EDIT: y'a en fait largement plus simple (enfin que ce que je t'ai proposé): un mix des deux soluces, une classe qui hérite de float, mais qui redéfinit __str__ d'ou est appelé automatiquement une méthode Round() si l'attribut dec (attribut défini dans __init__ d'après un de ses paramètres)...

  19. #19
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Petite variante en complément pour le formatage des nombres réels: on ajoute un nombre entier (optionnel) qui donne le nombre total de caractères du format, quitte à compléter à gauche par des espaces:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Round = lambda x, n, c=0: eval('"%' + str(int(c)) + '.' + str(int(n)) + 'f" % ' + repr(x))
     
    print Round(0.1, 4)
    0.1000
    print Round(0.1, 4, 10)
        0.1000
    Ce nombre entier complémentaire (c) n'est pris en compte que s'il est supérieur à l'affichage normal.

    A noter que si on veut faire la même chose pour des nombres réels contenus dans des listes, des tuples, des dictionnaires ou des nombres complexes, on est obligé de construire une fonction spécifique récursive par nature: http://python.jpvweb.com/mesrecettespython/arrond.

    Sinon, je suis impressionné par la solution de N.tox qui me donne plein d'idées .

    Tyrtamos

  20. #20
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    Et voici la version "optimisée", en fait, simplifiée : l'objet ne contient plus que deux attributs : val (le float) et d (le nombre de décimales à afficher si >0) :
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    class Float(object):
        __slots__=('d','val')
        def __init__(self,value=0.0,d=0):
            if type(value) in (int,long): value=float(value)
            if type(value)==self.__class__:value=value.val
            elif type(value)!=float: raise
            self.val=value
            self.d=0 if d<0 else d
        def __repr__(self):
            return '%s<Float>'%str(self.val)
        def __str__(self):
            val=str(self.val)
            num_dec=self.howManyDec(val)
            if self.d>0:
                if self.d==num_dec: return val
                else: return self.n_dec(self.d,_str=True)
            else: return val
     
        def howManyDec(self,string):
            val=string
            if 'e' not in val:
                dec=len(val.split('.')[-1])
            else:
                tmp=val.replace('-','')
                _float=val.split('e')[0].split('.')[0],int(val.split('e-')[1])
                dec=int(val.split('e')[1])+len(_float)
            return dec
     
        def to_f(self,other):
            if type(other) in (int,long,self.__class__):
                other=float(other)
            elif type(other)!=float: raise
            return other
        def to_F(self,other):
            if type(other)!=Float().__class__:
                other=Float(other)
            return other
        def __add__(self,other):return Float(self.val+self.to_f(other),self.d)
        def __radd__(self,other): return self.__add__(other)
        def __sub__(self,other):return Float(self.val-self.to_f(other),self.d)
        def __rsub__(self,other):return self.to_F(other).__sub__(self)
        def __mul__(self, other):return Float(self.val*self.to_f(other),self.d)
        def __rmul__(self,other): return self.__mul__(other)
     
        def __floordiv__(self,other):return Float(self.val//self.to_f(other),self.d)
        def __div__(self,other):return Float(self.val/self.to_f(other),self.d)
        def __truediv__(self,other): return self.__div__(other)
        def __rdiv__(self,other):return self.to_F(other).__div__(self)
     
        def __mod__(self,other):return Float(self.val%self.to_f(other),self.d)
        def __rmod__(self,other):return self.to_F(other).__mod__(self)
     
        def __divmod__(self,other): return (self.__div__(other),self.__mod__(other))
        def __rdivmod__(self,other):return self.to_F(other).__divmod__(self)
     
        def __pow__(self,other):return Float(self.val**self.to_f(other),self.d)
        def __rpow__(self,other):return self.to_F(other).__pow__(self)
     
        def round(self,string,integer,_str=False):
            val=string
            if '-' in val:
                val=val.replace('-','')
                sf=1
            else:
                val=val.replace('+','')
                sf=0
            if 'e' not in val:
                entier=val.split('.')[0]
                _float=val.split('.')[1]
            else:
                entier='0'
                _float,dec=val.split('e')[0],int(val.split('e')[-1])
                _float=_float.split('.')[0].rjust(dec,'0')+_float.split('.')[-1]
     
            if 10-int(_float[integer])>5:
                val=_float[:integer]
            else:
                val=str(int(_float[:integer])+1)
                if len(val)>integer:
                    entier,val=str(int(entier)+1),val[1:]
            val=('-'if sf==1 else '')+entier+'.'+val
            if _str:
                return val
            else:
                return Float(float(val),integer)
        def n_dec(self,integer,_str=False):
            if type(integer)!=int: raise
            val=str(self.val)
            if 'e' in val:
                val=self.ex_to_fl()
            if integer<len(val.split('.')[-1]):
                return self.round(val,integer,_str=_str)
            elif integer>len(val.split('.')[-1]):
                val=val+'0'*(integer-len(val.split('.')[-1]))
                if _str:
                    return val
                else:
                    return Float(self.val,self.d)
            else:
                if _str:
                    return val
                else:
                    return Float(self.val,self.d)
     
        def ex_to_fl(self):
            val=super(Float,self).__str__()
            if val[0]=='-':
                sf=1
                val=val[1:]
            else: sf=0
            dec=self.howManyDec()
            val=val.split('e-')[0].replace('.','')
            val=('-' if sf==1 else '')+'0.'+'0'*(dec-len(val))+val
            return val
     
     
        def __nonzero__(self):
            return (self.sf==1 and [0] or [1])[0]
     
        def __float__(self):
            return self.val
        def __int__(self):
            return int(self.__float__())
        def __long__(self):
            return long(self.__float__())
        def __complex__(self):
            return complex(self.__float__())
     
        def __neg__(self): return Float(-self.val,self.d)
        def __pos__(self): return self
        def __abs__(self): return Float(self.val,self.d)
     
        def __gt__(self,other):return self.val>self.to_F(other).val
        def __ge__(self,other):return self.val>=self.to_F(other).val
        def __eq__(self,other):return self.val==self.to_F(other).val
        def __ne__(self,other):return self.val!=self.to_F(other).val
        def __lt__(self,other):return self.val<self.to_F(other).val
        def __le__(self,other):return self.val<=self.to_F(other).val
    le code d'exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if __name__=='__main__':
        a=Float(Float(-5.888,10),1)
        print 'a=Float(-5.888,1) =',a
        b=a+9.768513+0.00016549
        print 'b= a+9.768513+0.00016549 =',b
        print 'Float(b,10) =',Float(b,10)
        b.d=15
        print 'b.d=15; b =',b
    Et le résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    a=Float(-5.888,1) = -5.9
    b= a+9.768513+0.00016549 = 3.9
    Float(b,10) = 3.8806784900
    b.d=15; b = 3.880678490000000
    @Tyrtamos : Je suis curieux de voir ta nouvelle recette

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Arrondi à 1 décimale
    Par Arkoze dans le forum Langage
    Réponses: 3
    Dernier message: 03/10/2011, 22h54
  2. affichage d'un float avec ses décimales
    Par wonderwhy dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 28/12/2010, 18h44
  3. pb - résultat de type double/float arrondi
    Par Ayana dans le forum Langage
    Réponses: 38
    Dernier message: 23/10/2007, 20h05
  4. Réponses: 2
    Dernier message: 07/07/2006, 19h59
  5. float arrondi depuis un fichier
    Par anasama dans le forum C++
    Réponses: 6
    Dernier message: 24/01/2006, 17h23

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