Problème de conversion avec StrToFloat [Résolu]

John Dogget 390 Messages postés vendredi 18 juin 2004Date d'inscription 7 mai 2009 Dernière intervention - 2 févr. 2007 à 15:57 - Dernière réponse : cs_Loda 900 Messages postés vendredi 3 novembre 2000Date d'inscription 30 juillet 2009 Dernière intervention
- 5 févr. 2007 à 09:24
Salut à tous.

Problème tous simple : quand j'utilise la fonction StrToFloat, Delphi semble rajouter des chiffres à la valeur réelle du nombre, et devient alors imprécis sur cette valeur

Exemple avec le code :

var
    NombreReel:extended;
    Chaine:string;
...
NombreReel:=StrToFloat(Edit1.Text);
Chaine:=FloatToStr(NombreReel);

Si on dis que Edit1.Text="12.3659", on constate que Chaine va être egale à "12.3658999999999..."

Pourquoi delphi ajoute ces chiffres ?
Comment l'eviter ?
Afficher la suite 

11 réponses

Répondre au sujet
John Dogget 390 Messages postés vendredi 18 juin 2004Date d'inscription 7 mai 2009 Dernière intervention - 2 févr. 2007 à 17:41
+3
Utile
Vous battez pas
J'ai trouvé mon erreur !!
En fait pour reprendre mon exemple de code plus haut, j'avais déclaré NombreReel comme un "real" et non comme un "extended".
Ca se passait bien à la compilation sauf que les fonction "FloatToStr" et "StrToFloat" ont besoin d'un "extended" pour travailler, et pas d'un "real".

Merci à vous deux
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de John Dogget
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 2 févr. 2007 à 16:50
0
Utile
Salut,

il est surprenant ton problème !

je viens de testé avec les infos que tu donnes et le resultat correspond exactement à la chaine

je me suis dit ... peut être un problème de version de Delphi

j'ai donc compilé avec D4 et D9 ... même résultat !!!

par contre si je déclare NombreReel en Single j'obtiens le même problème que tu décris

essaye voir en déclarant NombreReel en Currency   

 
@+
Cirec

Commenter la réponse de Cirec
cs_Loda 900 Messages postés vendredi 3 novembre 2000Date d'inscription 30 juillet 2009 Dernière intervention - 2 févr. 2007 à 16:57
0
Utile
salut,

Ce n'est pas delphi. C'est normal. Cela vient de l'encodage des nombre réel en mémoire.

les nombres sont stocké sous la form mantis - exposant - signe. donc la mantis (1.23659) est toujours arrondie à la plus proche puisssance de 2. donc, ce n'est pas exactement le nombre que tu tape au clavier.

Pour resoudre ce genre de problème,
- affiche tes nombre avec un format avec deciaml fixe ("format" vas bien pour ça)
- ou stock la valeur sous forme de string (beurk)

Loda

PS: je te conseille de te renseigner sur l'encodage en mémoire et les effets secondaire liées. ça peut-être la cause d'erreur dur à identifier. (ajout de petit nombre à un grand sans effet ; comparaison  d'égalité toujours fausse; ...)
Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
Commenter la réponse de cs_Loda
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 2 févr. 2007 à 17:03
0
Utile
@ Loda

je veux bien mais alors pourquoi chez moi ça fonctionne parfaitement

 
@+
Cirec

Commenter la réponse de Cirec
florenth 1105 Messages postés dimanche 1 août 2004Date d'inscription 17 août 2008 Dernière intervention - 2 févr. 2007 à 18:23
0
Utile
Salut,

Juste pour dire un mot au passage: lorsque vous avez beson de flottants, utilisez toujours "Double", c'est le meilleur compromis taille/précision.
Si vous avez besoin d'un max de précision, prenez "Extended" mais ne touchez jamais à Single, c'est une catastrophe sauf si c'est pour manipuler peu de chiffres significatifs (comme des coordonnées qui devront ensuite être arrondies au pixel près).

Voila, bonne prog'
A+
Flo
Commenter la réponse de florenth
jace1975 84 Messages postés mardi 31 mai 2005Date d'inscription 12 octobre 2007 Dernière intervention - 2 févr. 2007 à 19:27
0
Utile
Yo,

au passage y'a une fonction roundto , qui marche bien et qui permet notamment avec un truc genre setroundmode de définir le type d'arrondi sur un float.

++
Commenter la réponse de jace1975
cs_Loda 900 Messages postés vendredi 3 novembre 2000Date d'inscription 30 juillet 2009 Dernière intervention - 3 févr. 2007 à 19:42
0
Utile
@Cirec:

je dirais parceque :

soit tu n'as pas pris le même nombre que lui (et l'arrondi "tombe" juste pour toi).
soit l'arrondi dépend (aussi) de la machine.

Loda
Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
Commenter la réponse de cs_Loda
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 3 févr. 2007 à 21:06
0
Utile
Si j'ai pris le même nombre que lui

comment ça ... l'arrondi dépend aussi de la machine

la tu m'inquiètes sérieusement 
ce qui revient à dire qu'en fonction de la machine le résultat peut être juste où faux

Aïe Aïe Aïe ... ça ne m'arrange pas tout ça

on parle bien du type Extended parce que John Dogget à corrigé sa question en disant :
"j'avais déclaré NombreReel comme un "real" et non comme un "extended"."

@+
Cirec

Commenter la réponse de Cirec
cs_Loda 900 Messages postés vendredi 3 novembre 2000Date d'inscription 30 juillet 2009 Dernière intervention - 3 févr. 2007 à 22:41
0
Utile
J'avais eut ce problème il y quelques année en ADA lors que j'affichait un nombre avec 6 décimal, alors que je l'avait initilisé avec 3 seulement (genre 1.20  devient 1.1999999)

alors faisont un petit test:

context:
D6 Pro, P4m

avec le code donné par John, je n'ai pas de problème. Même string avant et après conversion.

Mais si je met 1.023999999999999  (et plus de 9) je recupère 1.025

Si tu fais des test sur la limit de la précision (cad en affichant le max de decimal):

NombreReel:=StrToFloat(Edit1.Text); // = 1.00000000000007 (a coller dans l'edit au runtime ou design time)
Chaine:=Format('%.18f',[NombreReel]);

// je lit 1.000000000000069920

Donc, j'ai moins de 15 chiffre significatif, alors que l'aide dit 19-20:
Extended    3.6 x 10^–4951 .. 1.1 x 10^4932    19–20    10

Loda

PS : "ce qui revient à dire qu'en fonction de la machine le résultat peut être juste où faux",
parce que toi, t'as jamais eut un programme qui marchait sur 10 machine identique sauf une?
ou un prog qui marchait pas sur certaine machine sans raison apparante?

De toute façon, il ne faux pas jouer trop près de la limit de précision des flottant. ça t'apporte toujours des emmerdes. Dans le doute, prend un type plus précis.

Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
Commenter la réponse de cs_Loda
florenth 1105 Messages postés dimanche 1 août 2004Date d'inscription 17 août 2008 Dernière intervention - 3 févr. 2007 à 23:08
0
Utile
Oui, il peut y avoir des différences assez imprévisibles, notamment au niveau des conversion Single -> Double -> Extended que demandent certaines fonctions.

Pour cela, deux remèdes :
- Une constante CNumDecimals = 15;
- Utilisation de SameValue(F1, F2, Power(10.0, - 2.0 * CNumDecimals)) au lieu Float1 = Float2
- Utilisation systématique de Format ou bien une autre fonction qui rend un nombre précis de chiffres significatifs.

Un peu compliqué ... mais en principe, on n'a pas souvent besoin de savoir si deux flottants sont strictement égaux. Cela n'a pas tellement de sens non plus, puisqu'il ne s'agit pas de valeur exacte mais d'arrondis.
Commenter la réponse de florenth
cs_Loda 900 Messages postés vendredi 3 novembre 2000Date d'inscription 30 juillet 2009 Dernière intervention - 5 févr. 2007 à 09:24
0
Utile
je suis bien d'accord avec toi. Et je prend note pour SameValue.

En passant, une erreur typique est la comparaison avec une const genre monflaot = 0.0 au lieu d'utiliser IsZero(monfloat).

bon, je vais arrêter là, sinon on vas écrire un article.

A+

Loda
Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
Commenter la réponse de cs_Loda

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.