# JAVA ne sait pas faire d'addition



## Philou1789 (29 Mai 2006)

Au secours, je fais des additions en Java avec des doubles et il n'y arrive pas:
HELP

Mon code
        double A = 84.4;
        double B = 53.2;
        double C = A + B;
        System.out.println("Tot="+C);
Le resultat:
        Tot=137.60000000000002



J'AI JAMAIS VU CA !!!!


----------



## Philou1789 (29 Mai 2006)

Pire regardez moi ca
        double A = 84.4;
        double B = 53.2;
        double C = A + B;
        if (C==137.60000000000002) 
            System.out.println("Tot 1="+C);
        else
            System.out.println("Tot 2="+C);


Et voilà la réponse:
       Tot 1=137.60000000000002


AU SECOURS


----------



## BeNBiBiFoKe (29 Mai 2006)

Curieux  

Encore pire quand je retire 137....


```
class test
{
        public static void main(String args[])
        {
        double A = 84.4;
        double B = 53.2;
        double C = A + B;
        C = C - 137.0;
        System.out.println("Tot="+C);
        }
}
```


```
ben-iMac:~/Desktop ben$ java test
Tot=0.6000000000000227
```

Cela s'explique par la représentation en base 2. Il y a forcément une erreur d'arrondi.


----------



## Philou1789 (29 Mai 2006)

c'est la cata, et plus je cherche pire c'est

float R = (float)-84.4;
       float T = (float)-53.2;
        float I = (float)3116.46;
        float P = R + T + I;
        System.out.println("Tot 2="+P);

Resultat:
Tot 2=2978.8599

FANTASTIQUE


----------



## Luc G (30 Mai 2006)

Entre deux nombres réels, il y en a une infinité (contrairement à ce qui se passe avec les entiers);

En informatique, on a un nombre fini de représentations de nombres : plus en double qu'en simple, mais de toutes façons en nombre fini.

Conclusion, les nombres réels ne sont pas représentés exactement par les nombres réels informatiques : on a des erreurs d'arrondi en général. En simple, on a en gros 7 chiffres significatifs corrects, en double plus ou moins le double mais de toutes façons, on n'a pas la valeur exacte.

La représentation des nombres est construite à partir de la base 2 et non de la base 10, ce qui rend le phénomène juste un peu plus visible parce que l'arrondi ne se fait pas sur les puissances de 10 mais sur les puissances de 2.

Java n'est donc pas en cause, tu aurais le même genre de problème en C, en Fortran, en Pascal  et tu as la même chose sur les calculatrices, etc. (sauf à utiliser des représentations très spécifiques qui permettent, non pas une précision infinie, mais du moins une précision aussi grande que ce que l'on veut).

Il faut apprendre à le gérer : par exemple, ne pas faire de test du genre " si le réel x est égal à 0.0" mais plutôt des tests du genre "si le réel x est inférieur à epsilon"


----------



## Philou1789 (30 Mai 2006)

Soit mais au finish, comment on s'en sort ? que propose tu ?


----------



## BeNBiBiFoKe (30 Mai 2006)

Comme Luc G l'explique si bien (et comme je l'évoque plus haut en edit ), il y a forcément une erreur d'arrondi. Du fait de représentation en base 2, il n'y a donc aucune raison qu'un arrondi se fasse dans ce cas-ci, qui est bien le cas.



```
class test
{
        public static void main(String args[])
        {
        double A = new Double("256.16");
        double B = new Double("16.4");
        double C = (double)A + (double)B;
        System.out.println(A +" + "+ B +" = "+C);
        }
}
```


----------



## Philou1789 (30 Mai 2006)

BeNBiBiFoKe a dit:
			
		

> ```
> class test
> {
> public static void main(String args[])
> ...



Marche pas ca chez moi


----------



## Luc G (30 Mai 2006)

Philou1789 a dit:
			
		

> Soit mais au finish, comment on s'en sort ? que propose tu ?



d'adapter ses besoins et les possibilités de l'informatique.

Il y a quelques cas dans la vie courante où on a besoins de plus de 6 chiffres significatifs, pas beaucoup où on a besoin de plus de 12 (c'est à dire de mieux que des doubles). Ensuite, c'est souvent un simple problème d'affichage : si tu affiches ton "137" avec 3 décimales, il n'y a plus d'erreur visible, si tu forces l'arrondi à la troisième décimale, tu vas même un peu plus loin que le visible.

Dans les cas où les 12 chiffres ne suffisent pas, soit il faut utiliser des représentation encore plus fines (genre des réels sur 12 ou 16 octets), soit il faut choisir des algorithmes où ces erreurs d'arrondi posent peu de problèmes.

Par exemple, quand il s'agit de résoudre des systèmes d'équations, donc couramment d'inverser des matrices, certaines méthodes (genre pivot) bloquent dès qu'on augmente la taille de la matrice (je me souviens avoir utilisé sous mac os 6  des réels en "extended" qui me permettaient de faire des approximations polynômiales de degré 12 ou 14 plutôt que 8 ou 10, ce qui suffisait dans le cas qui m'intéressait. S'il avait fallu aller au-delà, vu qu'il n'y avait pas (au moins de façon simple) de représentations adéquates, il aurait fallu changer d'algorithmes, passer par des procédures itératives plus lentes mais où ces problèmes se posent moins. C'est entre autres pour cette raison qu'ont été développés des tas d'algorithmes numériques de type itératif moins sensibles à ces problèmes.

Ce qui est assez "amusant", c'est que les problèmes de précision peuvent être vicieux, les bougres. Exemple typique (celui qui d'ailleurs pose problème pour l'inversion de matrices) quand tu dois manipuler des nombres très différents entre eux, exemple tu soustrais 1.0 de 1.0 e15, forcément, ta soustraction ne fait rien même si tes deux nombres ont l'air très simple : 1 dans les 2 cas mais avec une échelle complètement différente. Il faut donc se débrouiller pour éviter d'avoir des calculs de ce type.


----------



## BeNBiBiFoKe (30 Mai 2006)

Luc G a dit:
			
		

> d'adapter ses besoins et les possibilités de l'informatique.
> 
> Il y a quelques cas dans la vie courante où on a besoins de plus de 6 chiffres significatifs, pas beaucoup où on a besoin de plus de 12 (c'est à dire de mieux que des doubles). Ensuite, c'est souvent un simple problème d'affichage : si tu affiches ton "137" avec 3 décimales, il n'y a plus d'erreur visible, si tu forces l'arrondi à la troisième décimale, tu vas même un peu plus loin que le visible.
> 
> ...




Et merde....il est partit en suçette ! et Luc G, réveilles-toi  !


----------



## Luc G (30 Mai 2006)

BeNBiBiFoKe a dit:
			
		

> Et merde....il est partit en suçette ! et Luc G, réveilles-toi  !



 Dès qu'on parle d'arrondi, d'approximation et de toute cette sorte de choses, je me laisse aller, j'ai un brin baigné là-dedans et je rencontre encore dans mon boulot (bien que j'ai laissé les maths de côté il y a un certain temps) les problèmes vicieux dont je cause. C'est du vécu !


----------



## Savagnin (30 Mai 2006)

Luc G a dit:
			
		

> d'adapter ses besoins et les possibilités de l'informatique.
> 
> Il y a quelques cas dans la vie courante où on a besoins de plus de 6 chiffres significatifs, pas beaucoup où on a besoin de plus de 12 (c'est à dire de mieux que des doubles). Ensuite, c'est souvent un simple problème d'affichage : si tu affiches ton "137" avec 3 décimales, il n'y a plus d'erreur visible, si tu forces l'arrondi à la troisième décimale, tu vas même un peu plus loin que le visible.
> 
> ...



:casse: :casse: :casse: :rateau: :casse: :rateau: :rateau: :casse: :casse: :rateau: :rateau: 
Heu, bon ben moi, je retourne au forum arts graphiques...


----------



## tatouille (30 Mai 2006)

pépé luc  /michel simon accent / en 1923 j'avais déjà n**q*é ce p****n de floating-point


le mot IEEE754

http://grouper.ieee.org/groups/754/

tous les languages sont sujet à ce truc et en plus ca change suivant la platforme ...

 t'es pas sortie avec ça 

un petit jeux de floating-point ?  y'en a bien qui joue au sodoku mon c**l  


```
(c)tatouille
example darwin-dev-list
/*************************************************************/
#include <stdio.h>
#include <fenv.h>

int main(void)
{
  int save_rnd, rnd;
  double x, y, z;

  save_rnd = fegetround();
  if (save_rnd == FE_TONEAREST)
    printf("rounding direction is FE_TONEAREST\n");
  else
    printf("unexpected rounding direction\n");

  x = 1.79e308;
  y = 2.2e-308;
  z = x / y;                      /* overflow */
  printf("%g / %g = %g\n", x, y, z);

  x = -1.79e308;
  y = 2.2e-308;
  z = x / y;             /* negative overflow */
  printf("%g / %g = %g\n", x, y, z);

  fesetround(FE_TOWARDZERO);
  rnd = fegetround();
  if (rnd == FE_TOWARDZERO)
    printf("rounding direction is FE_TOWARDZERO\n");
  else
    printf("unexpected rounding direction\n");

  x = 1.79e308;
  y = 2.2e-308;
  z = x / y;                      /* overflow */
  printf("%g / %g = %g\n", x, y, z);

  fesetround(FE_UPWARD);
  rnd = fegetround();
  if (rnd == FE_UPWARD)
    printf("rounding direction is FE_UPWARD\n");
  else
    printf("unexpected rounding direction\n");
                                                /* continued */
/*************************************************************/
/*************************************************************/
  x = -1.79e308;
  y = 2.2e-308;
  z = x / y;             /* negative overflow */
  printf("%g / %g = %g\n", x, y, z);

/* return to round-to-nearest */
  fesetround(save_rnd);
  rnd = fegetround();
  if (rnd == FE_TONEAREST)
    printf("rounding direction is FE_TONEAREST\n");
  else
    printf("unexpected rounding direction\n");
}
/*************************************************************/
```


 
J'AI JAMAIS VU CA !!!!

j'espère que tu n'es pas developpeur ?


----------



## Luc G (30 Mai 2006)

tatouille a dit:
			
		

> tous les languages sont sujet à ce truc et en plus ca change suivant la platforme ...



Ben oui, la plate-forme, c'est comme ça qu'on pouvait utiliser les extended sur les 680x0 

Pour les langages, il faut prendre des langages à précision arbitraire genre OCaml par exemple (mais tout le monde ne connait pas ce genre de langage ). Rermarque, ça ne m'étonnerait pas qu'il y ait une bibli java pour faire ça mais comme je suis déconnecté de tout ça depuis longtemps...

Ceci dit, l'avantage de ce genre de problème, c'est que, au moins quand les gens s'aperçoivent qu'il y a un problème, ça peut les forcer à réfléchir à la différence entre math et informatique


----------



## tatouille (30 Mai 2006)

oui y a un truc pour aider sisi c'est dans la doc 
Java en plus a peut etre la doc la mieux faite quand on cherche un truc 

puis en plus il y a des profs, des chercheurs en math qui ont écrit des trucs pour Java...


c'était la Blague du Mardi offerte par Philou du 9 4


----------



## OlivierL (30 Mai 2006)

Reste la question, que vont devenir A et B ? Quel est vraiment le problème ?
Si c'est pour faire du calcul pur avec des doubles, soit la précision (ou plutôt l'imprécision  ) est tolérable, soit t'es dans le caca.

Si c'est pour afficher des nombres, il faut utiliser les classes qui vont bien (NumberFormat ou DecimalFormat ) c'est nécessaire, ne serait ce que pour utiliser les paramètres liés à la langue.


----------



## Luc G (30 Mai 2006)

tatouille a dit:
			
		

> J'AI JAMAIS VU CA !!!!
> 
> j'espère que tu n'es pas developpeur ?



je ne sais pas à qui ton message s'adresse 

Pour ma part, je ne suis plus développeur (et ne l'ai jamais été vraiment) mais je suis toujours confronté à des outils développés par d'autres 

Je fais joujou avec des boîtiers de télécontrôle qui donnent des résultats intéressants dans leurs calculs suite à ces problèmes d'arrondi, par exemple de bêtes différentiels sur des compteurs qui, parce que le compteur s'est réinitialisé à une valeur élevée (pour des raisons diverses et variées) se retrouvent minorés systématiquement juste de  quelques dizaines de pour cent, ce qui leur permet de rester plausibles tout en étant faux.

Comme il s'agit simplement de récupérer des résultats de mesures et pas de développer derrière, ces erreurs peuvent très facilement passer inaperçues, et pousser les gens à se gratter la tête quand ils voient les résultats, vu que les gens en question ne sont généralement ni développeurs, ni matheux.


----------



## molgow (31 Mai 2006)

BigDecimal pour avoir des réels avec une meilleure précision. Mais ce n'est pas la solution pour le problème de départ.


----------



## Luc G (31 Mai 2006)

molgow a dit:
			
		

> BigDecimal pour avoir des réels avec une meilleure précision. Mais ce n'est pas la solution pour le problème de départ.



Le problème de départ, c'est d'abord de savoir quelle est la précision nécessaire  

Si 6 ou 8 chiffres significatifs suffisent, il faut travailler en double puis afficher avec un format limité à 6 ou 8 chiffres significatifs, il n'y aura plus d'erreur apparente. Et l'erreur réelle ne portera que sur la 11 ou 12ème décimale. Sauf si on cumule pendant un bon moment les erreurs d'arrondi.

Que je sache, ça n'a pas empêché des tas de calculs de se faire depuis le premier ordinateur et le problème a toujours été présent puisqu'il est intrinsèque à la représentation d'une infinité par un ensemble fini. Les erreurs sont choquantes mathématiquement parlant(si on veut travailler "propre" il faut de la précision arbitraire) mais en pratique, il y a peu de situations où en même temps :
- ce soit gênant
- ce ne soit pas contournable en ajustant les algorithmes.


----------



## tatouille (31 Mai 2006)

Luc G a dit:
			
		

> Le problème de départ, c'est d'abord de savoir quelle est la précision nécessaire
> 
> ..ement parlant(si on veut travailler "propre" il faut de la précision arbitraire) mais en pratique, il y a peu de situations où en même temps :
> - ce soit gênant
> - ce ne soit pas contournable en ajustant les algorithmes.



:mouais: avec les impots je verifie au milliardieme de centime d'euro


----------



## Luc G (31 Mai 2006)

tatouille a dit:
			
		

> :mouais: avec les impots je verifie au milliardieme de centime d'euro



Ils sont pas fous aux impôts, ils ont dit : les centimes, on ne veut pas en entendre parler !


----------



## Imaginus (31 Mai 2006)

C'est donc qu'ils ont les pires programmeurs de la planete dans leurs rangs ? 


Ou il sont suffisament à faire avec les recouvrements...


----------



## Luc G (31 Mai 2006)

Imaginus a dit:
			
		

> C'est donc qu'ils ont les pires programmeurs de la planetes dans leurs rangs ?



Mais non : un bon programmeur commence par essayer de savoir précisément  ce qui est important pour le client afin de soigner ça aux petits oignons plutôt que de se prendre la tête avec ce qui ne l'est pas, important 

Et ce qui est important pour les impôts, c'est que l'argent rentre en évitant les problèmes, c'est pas quelques centimes qui poseront problème.


----------



## tatouille (1 Juin 2006)

Luc G a dit:
			
		

> Mais non : un bon programmeur commence par essayer de savoir précisément  ce qui est important pour le client afin de soigner ça aux petits oignons plutôt que de se prendre la tête avec ce qui ne l'est pas, important
> 
> Et ce qui est important pour les impôts, c'est que l'argent rentre en évitant les problèmes, c'est pas quelques centimes qui poseront problème.



c'est normal ils arrondissent au dessus  comme ça y'en a plus avec moins de soucis
 sont pas fous


----------



## Luc G (1 Juin 2006)

tatouille a dit:
			
		

> c'est normal ils arrondissent au dessus



même pas, il me semble  : ils virent les centimes (mais pour les déductions aussi, je crois )


----------



## lolo@esstin (1 Juin 2006)

Philou1789 a dit:
			
		

> Au secours, je fais des additions en Java avec des doubles et il n'y arrive pas:
> HELP
> 
> Mon code
> ...



Salut. Moi j'utilise du Fortran pour mes codes de CFD et je connais pas trop le java.
Mais en Fortran avec le simple compilateur G77 Gratuit,  J'ecrit :

    program add
      implicit none
      double precision :: A,B,C,D
      A=84.4d0
      B=53.2d0
      C=A+B
      D=C/137.6d0
      write(*,*) C,D
    end program add

et le resultat est : 137.6 et 1 excactement.

A mon avis tu dois pouvoir regler ton probleme avec une gestion du double precision plus pousse.

bye


----------



## tatouille (1 Juin 2006)

et pourquoi pas du gogol pardon heu cobol

j'ai un slogan : cobol tout pour les gogoles 

le problème est tout à fait envisageable en Java , 
c'est juste que java ( je ne sais qui est celui là)
devrait juste retourner à l'école


----------



## Luc G (1 Juin 2006)

tatouille a dit:
			
		

> et pourquoi pas du gogol pardon heu cobol



cobol objet, tant qu'à faire ! 

Sinon, j'ai toujours regretté (papi radote ) le fait que beaucoup se soient déshabitués du calcul mental : ça aidait à prendre conscience de ce qui est important et de ce qui l'est moins ! 


(Et sinon, ne parle pas de gogol, des fois que certains aient les doigts qui glissent et s'intéressent aux googols, on n'a pas fini d'avoir des problèmes d'arrondi )


----------



## tatouille (2 Juin 2006)

Luc G a dit:
			
		

> cobol objet, tant qu'à faire !
> 
> Sinon, j'ai toujours regretté (papi radote ) le fait que beaucoup se soient déshabitués du calcul mental : ça aidait à prendre conscience de ce qui est important et de ce qui l'est moins !
> 
> ...









pour ceux qui suivent on ne met pas souvent de photos à la cave mais je le trouve tres beau celui-ci


----------



## HommeCocoa (4 Juin 2006)

Luc G a dit:
			
		

> cobol objet, tant qu'à faire !
> 
> Sinon, j'ai toujours regretté (papi radote ) le fait que beaucoup se soient déshabitués du calcul mental : ça aidait à prendre conscience de ce qui est important et de ce qui l'est moins !
> 
> ...


 


Hahaha ouais les googolplex aussi


----------



## clampin (6 Juin 2006)

tatouille a dit:
			
		

> (grande image)
> 
> pour ceux qui suivent on ne met pas souvent de photos à la cave mais je le trouve tres beau celui-ci


whaou... c'est zoli tout plein ça... vivement que je puisse faire ça avec en C...


----------

