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

avec Java Discussion :

Arrondis explication methode


Sujet :

avec Java

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 442
    Points : 417
    Points
    417
    Par défaut Arrondis explication methode
    Bonjour,

    Je ne comprends définitivement pas comment fonctionnent les nombres en Java.

    J'ai un double a à approximer, et un double b qui détermine le pas de l'approximation.

    Par exemple, approxime(123.123, 0.2) doit renvoyer 123.2. C'est à dire, le nombre arrondi par pas de 0,2. un pas de 0,5 renverrait des nombres finissant par 0 ou 0,5.

    J'ai donc tenté toute une série de méthodes pour faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        private static double approxime(double d,double precision) {
            return Math.round(d/precision)*precision;
        }
        private static double approxime(double d,double precision) {
            return Math.floor(d/precision+0.5)*precision;
        }
        private static double approxime(double d,double precision) {
            return (int)(d/precision+0.5)*precision;
        }
        private static double approxime(double d,double precision) {
            return Math.round((float)(d/precision))*precision;
        }
    Sans succes. (résultats du type 123,2000000003)

    J'ai vu que beaucoup utilisaient aussi Math.pow. J'ai donc tenté vainement un magnifique

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        private static double approxime(double d,double precision) {
            return ((int)(d/precision+0.5))*Math.pow(10, Math.log10(precision));
        }
    Et obtenant encore le même résultat insatisfaisant, j'ai lentement glissé de la frustration à l'amertume, puis de l'amertume vers la dépression.

    Est-ce que quelqu'un pourrait me proposer une méthode fonctionnelle pour mon problème, et même, si ce n'est pas trop demander, m'expliquer pourquoi mes tentatives n'ont pas abouties.

    Un grand merci

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    En Java comme ailleurs, les nombres à virgule flottante ne font que des approximations. Par exemple il n'existe aucun moyen de représenter les nombres 0.2 ou 123.123 sous forme de double. Les expressions de type double que tu as indiquées, ne sont que des approximations de ces nombres.

    Assez souvent, cette suite d'approximations produit un résultat approximatif qui n'est pas le plus proche possible de ce que le résultat correct aurait été. Dans ce cas, l'erreur se voit à l'affichage.
    Il n'y a pas de solution. Ce qui est approximatif est approximatif. À la limite une solution c'est de travailler avec des nombres exacts, en virgule fixe et pas flottante, avec des long ou des BigDecimal. Mais dans ce cas certains calculs ne peuvent pas se faire, comme 1/3.

    À noter qu'avec l'exemple que tu donnes, je ne vois rien qui ressemble à 123,2000000003. Tous les résultats donnent 123,2.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 442
    Points : 417
    Points
    417
    Par défaut
    Ok. Alors j'ai une colle pour toi : (enfin plutôt pour moi en fait ) :
    J'ai essayé de ruser avec le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        private static double approxime(double d,double precision) {
            return precision<1 ? Math.round(d/precision)/((1/precision)) : Math.round(d/precision)*precision;
        }
    Et il se trouve que ça marche. Je n'ai plus d'apparitions de décimales à rallonge.

    Pourtant, j'ai simplement changé la multiplication de d par un double à virgule par la division de d par un entier dont la valeur approximative est sans virgule.

    Pourquoi ça marche ? Théoriquement, d'après ton message précédent, l'erreur venait de la multiplication de 2 nombres qui sont des valeurs approchées. Disons que précision vaut erratiquement 0,200000001, Pourquoi, alors 1/0,200000001 vaudrait 5 tout rond ?

    Plus géneralement, comment ça se fait que :
    d1 * d2 = résultat imprécis
    d1/(1/d2) = résultat différent plus précis

    Ou alors ça voudrait dire que Java arrondit arbitrairement en cours de calcul tout résultat qui s'approche d'un entier...

    En tout cas, merci pour ta réponse précedente.

    Oui, je n'ai pas testé sur 123,123. C'était un exemple au hasard. Mais sur une série de nombre, j'ai obtenu assez facilement des X,00000000Y

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par Sharcoux Voir le message
    Et il se trouve que ça marche. Je n'ai plus d'apparitions de décimales à rallonge.
    Moi je n'en avais pas non plus avec tes premiers exemples. Tout dépend des valeurs essayées. Il faut essayer d'autres valeurs pour tomber sur des résultats incorrects.

    Citation Envoyé par Sharcoux Voir le message
    Théoriquement, d'après ton message précédent, l'erreur venait de la multiplication de 2 nombres qui sont des valeurs approchées. Disons que précision vaut erratiquement 0,200000001, Pourquoi, alors 1/0,200000001 vaudrait 5 tout rond ?
    Par hasard. 5 tout rond, et beaucoup de nombres entiers, peuvent être représentés sous forme de double. Ce n'est pas étonnant que d étant la représentation double la plus proche de 0.2, 1/d donne la représentation double la plus proche de 5, en l'occurrence 5.
    Du coup cette division améliore la précision au lieu de la baisser, mais c'est un hasard, dû au choix des paramètres.

    Citation Envoyé par Sharcoux Voir le message
    Plus géneralement, comment ça se fait que :
    d1 * d2 = résultat imprécis
    d1/(1/d2) = résultat différent plus précis
    De manière générale ce n'est pas le cas. Mais ça peut arriver avec des d1 et d2 bien choisis. En l'occurrence tes "pas" d2 seront souvent des nombres qui ne se représentent pas en double, mais dont l'inverse se représente en double. Du coup c'est un facteur qui penche vers une meilleure précision. Mais d1 restant approximatif, et le résultat final aussi, ça ne marchera pas toujours.

    Citation Envoyé par Sharcoux Voir le message
    Ou alors ça voudrait dire que Java arrondit arbitrairement en cours de calcul tout résultat qui s'approche d'un entier...
    Nope. Java, comme tout le monde, arrondit au double le plus proche. Quand c'est un nombre entier, il arrondit à ce nombre entier.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 442
    Points : 417
    Points
    417
    Par défaut
    ok, je crois que j'ai compris.

    Dans l'exemple que j'ai donné, tout marchait pour toi à cause du 0.2 qui est probablement un double exact. avec 0.1 seule la dernière version que j'ai donnée marche. Avec 0.3, rien ne marche.

    Au final, j'ai fait ça. Ca marche pour tout (par contre, je renvoie une String au lieu d'un double, mais c'est tolérable dans mon cas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        private static String approxime(double d,double precision) {
                int l = (int)(Math.floor(Math.log10(precision)));//puissance de 10 de la précision (et donc du résultat)
                String[] E_d = ("" + ((int)(d/precision+0.5))*precision).split("\\.");//on sépare la partie Entière et la partie décimale
                if(E_d.length>1 && l<0) {return E_d[0] + "." + (E_d[1].length()<=-l ? E_d[1] : E_d[1].substring(0, -l));}//On coupe la partie décimale à la longueur voulu.
                else {return E_d[0];}
        }
    Par contre, si on rentre 1,5 comme précision, ça va pas marcher. En fait, je ne sais pas comment déterminer avec certitude si precision est un entier ou un entier avec une partie décimale.

    Comment je peux savoir si precision = 1,0 (entier) ou 1,0000000001 (décimal)

Discussions similaires

  1. [Toutes versions] Fonction Arrondi faq dvp, qq explications svp !
    Par mondev dans le forum VBA Access
    Réponses: 4
    Dernier message: 17/05/2010, 07h41
  2. [VB6] Racine carrée + arrondi
    Par Krys29 dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 28/10/2002, 13h19
  3. Explication procédure stockée
    Par underworld dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 09/09/2002, 10h51
  4. Recherche code d'un fifo,ou explication
    Par don-diego dans le forum C
    Réponses: 8
    Dernier message: 25/07/2002, 10h26
  5. recherches des cours ou des explications sur les algorithmes
    Par Marcus2211 dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 19/05/2002, 22h18

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