OVH Cloud OVH Cloud

Conversions de type, perte d informations

33 réponses
Avatar
Dominique de LAPASSE
Bonjour,

Imaginons que j 'ai besoin de convertir la valeur 17.58 ( Euros ) en 1758
( Centimes )

Le calcul qui vient naturellement à l esprit est :


float fValeur1 = (float)17.58;
float fValeur2 = fValeur1 * 100;

long lValeur3;
lValeur3 = (long) fValeur2;

Or lValeur3 vaut 1757 !!!
Quel calcul ou conversions faut-il mettre en oeuvre pour parvenir a un
résultat correct ????

Merci.

10 réponses

1 2 3 4
Avatar
Fabien LE LEZ
http://www.giromini.org/usenet-fr/repondre.html
Avatar
Fabien LE LEZ
On Thu, 17 Mar 2005 08:54:52 +0000 (UTC), Marc Boyer
:

En pratique, on calcule en entier avec la précision maximum demandée
(avec l'euro, 6 décimales après la virgule je crois),


S'il n'y a que des additions, des multiplications et des
soustractions, calculer en centimes d'euros suffit.

Ou on veut vraiment des flottants et on commence par recruter
un numéricien...


Et un numérologue pour savoir à l'avance si on a une chance de finir
ce #@$£%*! de programme.


--
;-)

Avatar
Jean-Marc Bourguet
Marc Boyer writes:

Dominique de LAPASSE wrote:
ou m et k sont entiers (et ^ designe l'exponentiation). 17.58 ne peut
pas se mettre sous cette forme et donc n'est pas representable
exactement.


Merci bien pour la theorie, mais en pratique , comment peux t on
resoudre ce probleme qui doit se poser assez souvent non ?


En pratique, on calcule en entier avec la précision maximum demandée
(avec l'euro, 6 décimales après la virgule je crois),


Les 6 decimales, c'etait pour les conversions entre monnaie nationale
et euros. Je ne sais pas si c'est valable aussi pour d'autres choses.

et on surcharge les fonctions d'E/S pour faire comme si il y avait
une virgule.

Ou on veut vraiment des flottants et on commence par recruter un
numéricien...


On engage aussi (surtout) un avocat pour recuperer la totalite de la
legislation applicable... et on espere qu'il n'y a pas de regles
impossibles a respecter. Le numericien va dire qu'on ne veut pas
simultanement des flottants et le respect des regles.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
kanze
Fabien LE LEZ wrote:
On Thu, 17 Mar 2005 09:25:19 +0100, "Dominique de LAPASSE"
:

(float)17.58;


La solution qui te vient naturellement à l'esprit est ce genre
de cast ? :-o

Imaginons que j 'ai besoin de convertir la valeur 17.58 (
Euros ) en 1758 ( Centimes )


Généralement, quand on parle d'argent, on évite au maximum
d'utiliser des flottants, car la valeur qu'ils stockent est
difficile à prévoir exactement.


Le problème n'est pas propre à l'argent. Dès qu'on a des valeurs
fractionnaires, il y a un problème de représentation.

Ce qui rend l'argent un peu spécial, c'est que la façon de
poursuivre dans ces cas est préscrite par la loi. Donc, par
exemple, dans la plupart des calculs, je suis obligé à arrondir
à 5 chiffres décimal après le virgule. Utiliser 52 chiffres
binaires (environ 17 chiffres décimal), comme fait le double sur
ma machine donne un résultat en fait plus précis, mais
juridiquement faux.

Et indépendamment de la législation, il y a souvent un aspect
« psychologique ». L'utilisateur lambda qui entre la suite de
caractères "17.58" s'attend à ce que la machine stocke la valeur
17,58. Or que c'est impossible avec des formats flottants
courants (qui sont soit base 2 soit base 16). Selon
l'application, on peut être amener à les prendre en compte.

On préfère utiliser des entiers, en prenant comme unité la
plus petite unité de la monnaie (ici, le centime).

Si tu n'as vraiment pas le choix, i.e. que tu es obligé de
faire une fonction qui prend en entrée un "double euros" et
qui renvoie la valeur en centimes, tu peux tenter ceci :

int ConversionEnCentimes (double euros)
{
return (euros * 100) + 0.5;
}


Fait gaffe quand même. Le résultat dans certains cas dépend de
la mode d'arrondie (même si ça doit marcher dans ce cas précis).

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Marc Boyer
Fabien LE LEZ wrote:
On Thu, 17 Mar 2005 08:54:52 +0000 (UTC), Marc Boyer
:

En pratique, on calcule en entier avec la précision maximum demandée
(avec l'euro, 6 décimales après la virgule je crois),


S'il n'y a que des additions, des multiplications et des
soustractions, calculer en centimes d'euros suffit.


En fait, ce sont les règles de conversions entre monnaies
qui se jouent à 6 décimales dans mon souvenir.
Comme tu le dis, tant qu'on reste dans les euros, on garde
2 décimales (3 pour vendre de l'essence).

Ceci dit, c'est une question qui doit etre résolue dans
le cahier des charges, pas sur un coin de table entre
développeurs.

Ou on veut vraiment des flottants et on commence par recruter
un numéricien...


Et un numérologue pour savoir à l'avance si on a une chance de finir
ce #@$£%*! de programme.


La numérologie pour les programmeurs, je le sens bien.
Faites un MD5 sur le .doc du cahier des charges, divisez
par le budget en Keuros, etc.
Y doit y avoir un marché.

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.


Avatar
Marc Boyer
Jean-Marc Bourguet wrote:
Marc Boyer writes:
Ou on veut vraiment des flottants et on commence par recruter un
numéricien...


On engage aussi (surtout) un avocat pour recuperer la totalite de la
legislation applicable... et on espere qu'il n'y a pas de regles
impossibles a respecter. Le numericien va dire qu'on ne veut pas
simultanement des flottants et le respect des regles.


Oui, mais entre temps, on a créé deux emplois nouveaux dans la
boite (le numéricien et l'avocat) ;-)
Les flottants font diminuer le chomage...

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.


Avatar
Fabien LE LEZ
On Thu, 17 Mar 2005 10:42:35 +0000 (UTC), Marc Boyer
:

Oui, mais entre temps, on a créé deux emplois nouveaux dans la
boite (le numéricien et l'avocat) ;-)
Les flottants font diminuer le chomage...


Ben non : les deux se contredisent pendant deux ans, le projet
n'avance pas, la boîte coule, et tous les employés se retrouvent au
chômage.

--
;-)

Avatar
Fabien LE LEZ
On 17 Mar 2005 02:08:13 -0800, :

Fait gaffe quand même.


D'une manière générale, je ne fais pas ;-)
Ou alors, dans des cas où une erreur d'une unité ou deux n'a guère
d'importance (du style, dans l'affichage d'une vidéo, quand je veux
calculer la largeur d'affichage (en pixels) d'après la hauteur de
l'écran : une erreur de 100 pixels serait gênante mais pas
catastrophique, et une erreur d'un pixel passe inaperçue).


--
;-)

Avatar
Falk Tannhäuser
Marc Boyer wrote:
Comme tu le dis, tant qu'on reste dans les euros, on garde
2 décimales (3 pour vendre de l'essence).


... et pour les factures de France Telecom. Puis, pour les
factures EDF, il faut 4 décimales.
Falk

Avatar
Michel Michaud
Dans le message ,
Fabien LE LEZ wrote:
int ConversionEnCentimes (double euros)
{
return (euros * 100) + 0.5;
}


Fait gaffe quand même. Le résultat dans certains cas dépend de
la mode d'arrondie (même si ça doit marcher dans ce cas précis).


Ça « doit » marcher ? Vraiment ? Est-ce que c'est garanti par la
norme que les valeurs sont tronqués lorsqu'elles sont stockées ? Par
exemple, que 17.58 mis dans un double sera égal ou plus petit ? Je
ne crois pas (et je me demande si c'est ce que tu veux dire par
« dépend du mode d'arrondie »). Si la valeur peut être plus grande,
ce que je crois, alors le +0.5 fera passé à la prochaine unité, ce
qui est incorrect. Je ne crois pas que la solution soit aussi
simple, du moment où, une fois stockée, on ne peut pas savoir
quelle était vraiment la valeur initialement obtenue...

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/


1 2 3 4