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

C# Discussion :

Multiplication d'un float avec Math.Pow()


Sujet :

C#

  1. #1
    Membre du Club Avatar de Lelio1407
    Inscrit en
    Juillet 2009
    Messages
    126
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 126
    Points : 68
    Points
    68
    Par défaut Multiplication d'un float avec Math.Pow()
    Bonjour,

    Le but de mon programme est de convertir un float (qui peut aller jusqu'à 9 chiffres après la virgule) pour écriture dans un fichier binaire.
    Afin de ne pas m'embêter avec la virgule du float, je me suis dit qu'il me suffisait de le multiplier par 10 exp.9 et de convertir cet UInt32 en Byte[4].
    Tout fonctionne bien si j'ai effectivement 9 chiffres après la virgule. Si par contre, mon float = 0.1, alors 0.1*Math.Pow(10,9) = 100000001! Idem si je fais : 0.1*1000000000 = 100000001.
    Quelqu'un peut-il m'expliquer cet effet de bord?
    Je vous remercie...

  2. #2
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Février 2003
    Messages
    2 182
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2003
    Messages : 2 182
    Points : 4 496
    Points
    4 496
    Par défaut
    Le float a une précision de 7 chiffres après la virgule
    Le double a une précision de 15 chiffres après la virgule

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
                float val;
                val =(float) (0.1 * Math.Pow(10, 9));
    J'obtient la bonne valeur

    Peut-être afficher ton code (déclaration des variables, et le calcul), et j'ai pas compris l'histoire du byte[4]...

  3. #3
    Rédacteur
    Avatar de SaumonAgile
    Homme Profil pro
    Team leader
    Inscrit en
    Avril 2007
    Messages
    4 028
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Team leader
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2007
    Messages : 4 028
    Points : 6 334
    Points
    6 334
    Par défaut
    Tu peux aussi utiliser des decimal au lieu des float si possible, ça évitera ce genre de problèmes.

  4. #4
    Membre du Club Avatar de Lelio1407
    Inscrit en
    Juillet 2009
    Messages
    126
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 126
    Points : 68
    Points
    68
    Par défaut
    Merci pour vos réponse.
    Le probleme est que je souhaite me passer de la virgule.
    Le résultat de ma multiplication est donc stocké dans un UInt32.
    Voici le code complet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public void SetParametersBinary()
    {
         _parametersBinary_CoeffA = new Byte[4];
         UInt32 parametersBinary_CoeffA_Temp = (UInt32)(CoeffA *Math.Pow(10,9));
         _parametersBinary_CoeffA[0] = (Byte)(parametersBinary_CoeffA_Temp & 0xFF);
         _parametersBinary_CoeffA[1] = (Byte)((parametersBinary_CoeffA_Temp & 0xFF00) >> 8);
         _parametersBinary_CoeffA[2] = (Byte)((parametersBinary_CoeffA_Temp & 0xFF0000) >> 16);
         _parametersBinary_CoeffA[3] = (Byte)((parametersBinary_CoeffA_Temp & 0xFF000000) >> 24);
    }
    C'est lorsque j'ai CoeffA = 0.1 (par exemple) que :
    UInt32 parametersBinary_CoeffA_Temp = 0.1*Math.Pow(10,9) = 100000001 alors qu'il devrait être égal à : 100000000
    NB : je ne peut utiliser l'opérande & avec un float ou un décimal.

    Sinon, si quelqu'un sait convertir float -> byte[4] directement...;-)

  5. #5
    Membre chevronné
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Points : 2 209
    Points
    2 209
    Par défaut
    Bonjour,

    Je te suggère de regarder du côté de la classe BitConverter et plus particulièrement ses méthodes statiques GetBytes(float) et ToSingle(byte[], int)

    Cordialement !

  6. #6
    Membre du Club Avatar de Lelio1407
    Inscrit en
    Juillet 2009
    Messages
    126
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 126
    Points : 68
    Points
    68
    Par défaut
    Merci. Effectivement, pour "binariser" des floats, la méthode BitConverter.GetBytes(myFloat) fonctionne très bien!

  7. #7
    Membre éprouvé Avatar de kheironn
    Homme Profil pro
    Chef de projets technique C# / MVC / .Net
    Inscrit en
    Février 2007
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets technique C# / MVC / .Net
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2007
    Messages : 822
    Points : 1 108
    Points
    1 108
    Par défaut
    Citation Envoyé par Lelio1407 Voir le message
    Si par contre, mon float = 0.1, alors 0.1*Math.Pow(10,9) = 100000001! Idem si je fais : 0.1*1000000000 = 100000001.
    Quelqu'un peut-il m'expliquer cet effet de bord?
    Je vous remercie...
    0.1 n'existe pas réellement en Float. Ce sera un truc du genre 0.100000001 qui sera stocké.

    Les nombres à virgule flottante n'ont pas de bonne précision du fait même de leur nature. FAire des produits ou des quotients avec ces derniers est un bon moyen de se tirer une balle dans le pied. D'où le fait qu'en monétaire on n'utilise JAMAIS ces types. Un décimal, avec une précision de 0.00001 est conseillé et ne génère AUCUNE erreur d'approximation. Inconvéniant, c'est un poil moins rapide. Mais l'exactitude des données n'est-elle pas à privilégier sur un gain de vitesse de quelques microsecondes ?

  8. #8
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 493
    Points
    5 493
    Par défaut
    S'il s'agit d'une sérialisation binaire, pourquoi ne pas tout simplement utiliser BinaryWriter.Write(float) ?

    Sinon, en unsafe... uint someInteger= *(uint*)(&someFloat); Autrement dit, on récupère l'adresse du float, on la traite comme l'adresse d'un entier puis récupère le contenu du pointeur. Les bits de someFloat et someInt sont alors identiques. Note: il faut intercaler un cast vers void* si le compilateur C# joue son pointilleux.

    Sinon, pour l'effet de bord comme tu disais... Il faut comprendre que les réels (float ou double) sont stockés sous la forme : A*2^B.
    Notamment : 0.1 (décimal) = 1/16 + 1/32 + 1/256 + ... = 0.000110011.. (binaire). Ici, A = 1.10011 et B = -100 (-4 en décimal)

    En réalité, dans la norme IEEE pour les virgules flottantes, ce sera plutôt A = 110011... (23 bits) et B = 106 (décimal) avec A*2^(B - 127). Puisque 106 + 23 - 4 = 127

  9. #9
    Membre éprouvé Avatar de kheironn
    Homme Profil pro
    Chef de projets technique C# / MVC / .Net
    Inscrit en
    Février 2007
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets technique C# / MVC / .Net
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2007
    Messages : 822
    Points : 1 108
    Points
    1 108
    Par défaut
    pour les float et double, je ne connaissais pas la formule exacte, mais j'avais une idéee s'y rapprocahnt ...

    merci bien !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème avec Math.Pow()
    Par darkloy dans le forum C#
    Réponses: 1
    Dernier message: 07/04/2012, 22h33
  2. erreur avec math.pow
    Par ricky78 dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 30/01/2011, 20h51
  3. Réponses: 1
    Dernier message: 05/01/2006, 19h43
  4. Float avec une virgule ?!
    Par yan dans le forum C++
    Réponses: 3
    Dernier message: 23/11/2005, 18h21
  5. [Struts]validation de Integer et de Float avec Validator
    Par jklassen dans le forum Struts 1
    Réponses: 6
    Dernier message: 28/07/2004, 14h03

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