Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3209 connectés 

  FORUM HardWare.fr
  Programmation
  Java

  [résolu] calcul faux

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[résolu] calcul faux

n°1443968
moustik510
Enfin en travaux !
Posté le 18-09-2006 à 11:08:21  profilanswer
 

[résolu] : On va multiplier par 100, merci  :jap:  
 
Bonjour,
 
Petits soucis : je me relance dans la prog Java avec quelques oublis....
 
Je récupère dans un fichier un montant (float) et un nombre (int).
Je récupère donc cela dans des chaines de caractères que je convertis ensuite en float ou int.
 
float montant = Float.parseFloat("7.7" ); //Exemple d'une valeur que je peux avoir
int nombre = Integer.parseInt("3" );
// Ensuite produit classique
float total = montant * nombre.
 
[#f0000e]Et là, au lieu d'avoir 23.1, j'ai 23,09.............. (pleins de chiffre derrières)
 
??? Une idée ?
 
Merci d'avance.


Message édité par moustik510 le 18-09-2006 à 12:04:57
mood
Publicité
Posté le 18-09-2006 à 11:08:21  profilanswer
 

n°1443969
flo850
moi je
Posté le 18-09-2006 à 11:09:40  profilanswer
 

les nombres décimaux sont rarement stockés sous leur forme exact , mais sous une valeur approchée ( d'assez pres )  
 

n°1443974
moustik510
Enfin en travaux !
Posté le 18-09-2006 à 11:16:57  profilanswer
 

OK donc la dessus je fais un arrondi à deux décimales près pour obtenir mon montant exact. (C'est la solution temporaire que j'avais utilisé mais je voulais avoir une explication !)
C'est la meilleure solution ?
 
Merci en tout cas pour ta réponse super rapide.

n°1443977
gocho
Posté le 18-09-2006 à 11:18:04  profilanswer
 

utilises des doubles au lieu des floats et tu auras le resultat que tu veux :)


---------------
Mon feedback
n°1443979
jagstang
Pa Capona ಠ_ಠ
Posté le 18-09-2006 à 11:19:55  profilanswer
 

oui car les nombres pseudo-réels sont stockés en binaire, par puissance de 2 successives.
 
or, 0.1 ne peut pas être stocké entièrement par puissance de 2 (0.0625+0.03125 etc)


---------------
What if I were smiling and running into your arms? Would you see then what I see now?  
n°1443980
jagstang
Pa Capona ಠ_ಠ
Posté le 18-09-2006 à 11:20:24  profilanswer
 

gocho a écrit :

utilises des doubles au lieu des floats et tu auras le resultat que tu veux :)


ça ne change rien au problème, ça le repousse


---------------
What if I were smiling and running into your arms? Would you see then what I see now?  
n°1443991
moustik510
Enfin en travaux !
Posté le 18-09-2006 à 11:27:22  profilanswer
 

jagstang a écrit :

ça ne change rien au problème, ça le repousse


 
Que faire dans un tel cas alors ?
stocker les valeurs * 2 ?

n°1443993
Ricco
Retour au pays
Posté le 18-09-2006 à 11:28:01  profilanswer
 

Je savais que Java n'était pas le meilleur langage pour faire des calcul mais quand même là :D
 

Code :
  1. int nombre1 = 3;
  2.         int nombre2 = Integer.parseInt("3" );
  3.         double montant = 7.7 ;
  4.         float montant2 = Float.parseFloat("7.7" );
  5.         double montant3 = Double.parseDouble("7.7" );
  6.        
  7.         System.out.println( nombre1*montant + " " + nombre2*montant2 + " " + nombre2*montant3 );


ça me donne 23.1 23.099998 23.1
 
Netbean me prévient d'une possible perte de précision avec "montant" en float. En prennant des double le résultat semble meilleur mais c'est pê reculer pour mieux sauter, que ce passe-t-il avec un "gros" double ?


---------------
"L'informatique n'est pas plus la science des ordinateurs que l'astronomie n'est celle des télescopes." Michael R. Fellows & Ian Parberry
n°1443996
jagstang
Pa Capona ಠ_ಠ
Posté le 18-09-2006 à 11:29:37  profilanswer
 

moustik510 a écrit :

Que faire dans un tel cas alors ?
stocker les valeurs * 2 ?


je vois pas ce que ça change  :sweat:


---------------
What if I were smiling and running into your arms? Would you see then what I see now?  
n°1443998
jagstang
Pa Capona ಠ_ಠ
Posté le 18-09-2006 à 11:29:59  profilanswer
 

une solution con aussi : calculer en centimes (avec des entiers donc)


---------------
What if I were smiling and running into your arms? Would you see then what I see now?  
mood
Publicité
Posté le 18-09-2006 à 11:29:59  profilanswer
 

n°1444005
Taz
bisounours-codeur
Posté le 18-09-2006 à 11:40:25  profilanswer
 

dès que tu fais du monétaire il __faut__ travailler avec des types entiers (j'ai pas dit int, j'ai dit type entier, arithmétique entière). Si t'as un flottant dans le tas, c'est foutu.

n°1444016
flo850
moi je
Posté le 18-09-2006 à 11:51:36  profilanswer
 

Ricco a écrit :

Je savais que Java n'était pas le meilleur langage pour faire des calcul mais quand même là :D
 
Netbean me prévient d'une possible perte de précision avec "montant" en float. En prennant des double le résultat semble meilleur mais c'est pê reculer pour mieux sauter, que ce passe-t-il avec un "gros" double ?


 
le problème est le même dans tous les langages  
regarde sur cette page : http://www.arcanapercipio.com/gen/binaire/bin-nb.php la partie http://www.arcanapercipio.com/gen/binaire/bin-nb.php
 
 

jagstang a écrit :

une solution con aussi : calculer en centimes (avec des entiers donc)


 

Taz a écrit :

dès que tu fais du monétaire il __faut__ travailler avec des types entiers (j'ai pas dit int, j'ai dit type entier, arithmétique entière). Si t'as un flottant dans le tas, c'est foutu.


 
+1  
si tu dois aller au millieme de centime pret , tu multiplie toutes nombres par 100 000
lors de l'affichage tu fais la manip inverse

n°1444022
masklinn
í dag viðrar vel til loftárása
Posté le 18-09-2006 à 11:58:53  profilanswer
 

Ricco a écrit :

Je savais que Java n'était pas le meilleur langage pour faire des calcul mais quand même là :D


Ce problème n'a strictement aucun rapport avec Java et n'est en rien spécifique à l'utilisation de Java, il trouve son origine dans la représentation binaire des nombres flottants (norme IEEE754): certains nombres flottants décimaux exacts ne peuvent être encodés de manière exacte en binaire. Tous les langages utilisant un type réel "floating-point" sont affectés. Certains langages disposent par ailleurs d'un type réel "fixed-point" dont la précision est exacte et fixée sur une range donnée, et d'un type "decimal" à la précision infinie (mais notablement moins efficace, et prenant largement plus de place)
 
De même que certaines fractions ne peuvent être encodées de manière exacte en décimal (1/3 ~ 0.333~)
 
Merci, donc, d'arrêter de raconder des conneries, et de lire What Every Computer Scientist Should Know About Floating-Point Arithmetic


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°1444023
moustik510
Enfin en travaux !
Posté le 18-09-2006 à 12:00:44  profilanswer
 

flo850 a écrit :

+1  
si tu dois aller au millieme de centime pret , tu multiplie toutes nombres par 100 000
lors de l'affichage tu fais la manip inverse


 
Ah ... ça me dis quelque chose ça. on a du me le dire pendant les cours... mais j'ai pas du le noter. Et je n'utilise pas Java professionnellement (dev SAP) donc j'évolue pas.
 
Je vais faire de la multiplication par 100. Merci pour vos réponse. Comment passer le sujet en résolut ?

n°1444025
jagstang
Pa Capona ಠ_ಠ
Posté le 18-09-2006 à 12:01:59  profilanswer
 

edit ton premier post


---------------
What if I were smiling and running into your arms? Would you see then what I see now?  
n°1444052
Taz
bisounours-codeur
Posté le 18-09-2006 à 13:11:52  profilanswer
 
n°1444159
moustik510
Enfin en travaux !
Posté le 18-09-2006 à 15:11:25  profilanswer
 

Taz a écrit :

BigDecimal :o


 
C'est pour toi la meilleure solution ?
(Sachant que je ne travaillerai pas avoir des nombres très grands mais pour être plus propre ...)

n°1444166
MagicBuzz
Posté le 18-09-2006 à 15:22:11  profilanswer
 

Decimal tout court doit faire l'affaire logiquement. A moins qu'e Java Decimal soit un alias de Float, il utilise une précision fixe, et donc ne pose pas ces problèmes d'approximation (si ?)
Mais sinon, *100 et dans un Int ça reste de loin la meilleure solution.

Message cité 1 fois
Message édité par MagicBuzz le 18-09-2006 à 15:22:40
n°1444180
Taz
bisounours-codeur
Posté le 18-09-2006 à 15:43:25  profilanswer
 

MagicBuzz a écrit :

Decimal tout court doit faire l'affaire logiquement. A moins qu'e Java Decimal soit un alias de Float, il utilise une précision fixe, et donc ne pose pas ces problèmes d'approximation (si ?)
Mais sinon, *100 et dans un Int ça reste de loin la meilleure solution.


Si. Il suffit de faire 3 * 0.7. Ce qui est donc complètement pourri. En compta t'es pas la pour jouer à madame irma. le Calcul doit être exact du début jusqu'à la fin. Si tu fais une somme de float, l'imprécision se propage et grandit linéairement. Et là tu plantes ta compta.
 
BigDecimal c'est très bien, et t'auras une bonne propagation d'échelle que tu pourras gérer toi même. Par exemple du fais un calcul avec la précision maximale genre 175.25 * 0.03 ça va te faire du 5.2575 et quand tu enregistres tes données, tu peux tronquer. Comme ça c'est parfait, tu as fait le calcul exact tout le long.

n°1444188
MagicBuzz
Posté le 18-09-2006 à 15:55:50  profilanswer
 

Ma question était : est-ce que Decimal en Java est comme le Decimal en SQL, c'est à dire TOUT SAUF UN FLOAT. (en réalité, une chaîne de caractères d'un nombre fixe de chiffres).
 
Ce type (en SQL tout du moins) permet de stocker des valeurs à virgule d'une façon très précise, sans le moindre risque d'erreur d'arrondi.
 
Et Decimal tout court devrait suffir amplement. BigDecimal, comme tout "big", n'est qu'une solution pourrie pour repousser le problème d'arrondi, sans s'en protéger.
 
Dans tous les cas, une application COMPTA ne compte qu'en entiers, ou en types à précision fixe (Decimal en SQL donc). Jamais de la vie en float, même si c'est un float sur 64 bits avec une "grande précision" car dès qu'on fait 1 + 1, même avec 64 bits de précision, un float va faire une erreur de calcul. Avec un type Decimal, ce n'est pas le cas, à moins qu'on ne dépasse le nombre de chiffres pour la représentation. (gare au /3 par exemple)


Message édité par MagicBuzz le 18-09-2006 à 15:56:43
n°1444190
Taz
bisounours-codeur
Posté le 18-09-2006 à 15:56:21  profilanswer
 

Je reprécise : BigDecimal c'est bien mieux que des int parce que dans ta compta, tu as des multiplication avec des fractions, et le temps de l'opération, tu as besoin (obligatoire) de précision supplémentaire. C'est vraiment important quand le calcul doit être exact.
 
Surtout avec des float, quand tu mélanges des nombres d'ordre très différents, ça devient très tendu.

n°1444191
flo850
moi je
Posté le 18-09-2006 à 15:56:35  profilanswer
 

moustik510 a écrit :

Ah ... ça me dis quelque chose ça. on a du me le dire pendant les cours... mais j'ai pas du le noter. Et je n'utilise pas Java professionnellement (dev SAP) donc j'évolue pas.
 
Je vais faire de la multiplication par 100. Merci pour vos réponse. Comment passer le sujet en résolut ?


quitte a mettre en place un systeme de ce type , garde toi un peu de marge : multiplie pas 1 000 ou 10 000

n°1444194
Taz
bisounours-codeur
Posté le 18-09-2006 à 15:58:21  profilanswer
 

oui BigDecimal c'est comme celui du SQL.
 
je connais pas Decimal en java, juste java.math.BigDecimal.

n°1444198
MagicBuzz
Posté le 18-09-2006 à 16:00:05  profilanswer
 

A priori, y'a pas de raison pour que Decimal ne soit pas pareil que BigDecimal donc ;)
 
Sauf que l'un doit avoir une précision de 40 chiffres alors que l'autre n'a une précision que de 20 chiffres mettons. (à compter que Decimal existe hein, moi je ne connais pas Javs ;))
 
Toujours est-t-il que dans ce cas, je suis d'accord avec ta solution. BigDecimal est dont parfaitement adapté, car garantie une précision fixe, ce qu'on utilise effectivement en compta.
 
Et oui, en compta :
 
10.00 / 3 * 3 = 9.99 et non 10 ! (d'où l'importance de travailler en précision fixe)


Message édité par MagicBuzz le 18-09-2006 à 16:01:49
n°1444211
souk
Tourist
Posté le 18-09-2006 à 16:21:41  profilanswer
 

sauf que Decimal en java ca n'existe pas [:pingouino]

n°1444214
MagicBuzz
Posté le 18-09-2006 à 16:24:41  profilanswer
 

Ben forcément :spamafote:
 
C malin aussi d'appeler un champ Bigxxx alors que le type "de base" n'existe pas :o

n°1444236
Taz
bisounours-codeur
Posté le 18-09-2006 à 16:58:49  profilanswer
 

c'est pour avoir la plus grosse :o

n°1466655
rom1v
Posté le 28-10-2006 à 18:12:55  profilanswer
 

Taz a écrit :

l'imprécision se propage et grandit linéairement.


Il n'y a pas de raison que l'évolution de l'imprécision soit linéaire :)
 
Sinon, juste pour compléter les réponses, un nombre à virgule flottante est composé de 3 "champs": un bit de signe, un exposant, une mantisse (S|E|M).
Pour un float, 32 bits, répartis comme ceci : (1|8|23).
Pour un double, 64 bits, répartis comme ceci : (1|11|52).
 
Le nombre de chiffres significatifs est donc de 23 en base 2 pour un float (donc 23 * ln2/ln10 ~= 7 en base 10) et de 52 en base 2 pour un double (donc 52 * ln2/ln10 ~= 16 en base 10).
 
Ca c'est pour le stockage "brut". Après, c'est les opérations qui font perdre de l'imprécision, notamment l'addition de 2 nombres d'ordre de grandeur très différents (absorption) ou la soustraction de 2 nombres très très proches (cancellation).
Les multiplications n'entraîne pas de perte d'information autre que celle du stockage du résultat.

n°1472052
Taz
bisounours-codeur
Posté le 08-11-2006 à 09:54:39  profilanswer
 

rom1v a écrit :

Il n'y a pas de raison que l'évolution de l'imprécision soit linéaire :)

tu as raison, c'est toujours pire que linéaire.

n°1472057
rom1v
Posté le 08-11-2006 à 10:08:27  profilanswer
 

Petite correction par rapport à ce que j'ai dit, le nombre de chiffres significatifs est la taille de la mantisse + 1 (car il y a un 1 implicite), et donc pour un float, 23 chiffres significatifs en base 2, et en double 53...

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Java

  [résolu] calcul faux

 

Sujets relatifs
Comportement Bizare de mon COOKIE [RESOLU][Resolu] Addition de deux elements de deux vecteurs
[Résolu] [C#] String et Split[résolu][c#] ajout d un element à un tableau
suppression ou cacher ligne sur bouble infini[résolu][Résolu][Qt] QProcess lancés en boucle - started() et finished()
Récupérer le Full Name d'un utilisateur réseau en VBA [Résolu]selection Listbox avec multiselected [résolu]
[RESOLU] Evénement onclick()[Résolu] Mon script d'ouverture de pop-up ne doit pas être bon !
Plus de sujets relatifs à : [résolu] calcul faux


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR