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

Java Discussion :

Problème d'arrondi avec des opérations simples de soustraction et d'addition


Sujet :

Java

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 802
    Points : 653
    Points
    653
    Par défaut Problème d'arrondi avec des opérations simples de soustraction et d'addition
    Je viens de réaliser que de simples opérations d'addition ou de soustraction peuvent engendrer des problèmes d'arrondi avec certaines valeurs.

    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    System.out.println(71.19 - 98);
    Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    -26.810000000000002
    Existe-t-il un moyen pour résoudre ces problèmes ?

  2. #2
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Points : 2 161
    Points
    2 161
    Par défaut
    salut,

    c'est inhérent à la façon dont les ordinateurs stockent les nombres décimaux, qu'on appelle nombres flottants (cf. l'article de wikipédia

    Si tu veux t'assurer que tes valeurs soient exactes et que tu connais bien ta précision voulue et la valeur du plus grand nombre à stocker, le plus simple est encore de stocker ta valeur dans un entier (int) et de retenir un facteur à l'entier stocké. Par exemple, tu décides que ta précision maximale est de deux décimales et tu stockes dans ta variable un nombre entier de centièmes:

    Par exemple, tu veux calculer 71.19 - 98:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int a = 7119 (car 7119 / 100 = 71.19)
    int b= 9800 (car 9800 / 100 = 98)
     
    int res = a - b; // res = -2681, soit exactement -26.81
    attention: la valeur maximale stockable par ton 'int' ne vaut maintenant plus que Integer.MAX_VALUE / 100 .

    De plus, choisir une base (ci-dessus, la valeur 100) qui soit une puissance de 2 (comme 128 par exemple) permet d'effectuer les conversions "valeur réelle <=> valeur stockée" encore plus rapidement grâce aux opérateurs de décalage de bits (<< et >>>).

    Ce principe est d'ailleurs couramment utilisé pour des petits calculs en 2D car faire des opérations simples (+ - * /) sur des entiers est bien plus performant que les mêmes opérations avec des nombres flottants.

    Last but not least: A noter également que si tu veux quelque chose de plus évolué, tu as java.math.BigDecimal qui est dévolue à ce genre de besoin.
    Mon projet du moment: BounceBox, un jeu multijoueurs sur Freebox, sur PC et depuis peu sur smartphone/tablette Android.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 802
    Points : 653
    Points
    653
    Par défaut
    Ok merci

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 81
    Points : 84
    Points
    84
    Par défaut
    Voici la consigne que nous avons mis en place pour les développements Java :

    Etant donné que tout calcul avec des réels (float ou double) peut renvoyer des approximations, un arrondi à n chiffres après la virgule devra être réalisé sur le résultat de tous les calculs avec des réels.
    C’est à la charge du développeur de déterminer le nombre significatif de chiffres après la virgule pour l’arrondi.
    d = (Math.round(d*Math.pow(10,n))) / (Math.pow(10,n); // n correspond au nombre de chiffres après la virgule à conserver

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

Discussions similaires

  1. [AC-2003] Problème d'arrondi avec les champs de type réel simple
    Par gege2061 dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 15/09/2009, 17h58
  2. [Tableaux] Problème de foreach avec des checkboxes
    Par nanor21 dans le forum Langage
    Réponses: 10
    Dernier message: 15/05/2006, 01h04
  3. Problème de buffer avec des int et des char
    Par Lolita59 dans le forum Réseau
    Réponses: 23
    Dernier message: 04/05/2006, 11h09
  4. Problème de "select" avec des valeurs a null
    Par SchpatziBreizh dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 01/07/2005, 16h08
  5. Réponses: 6
    Dernier message: 19/10/2004, 13h46

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