Problème sur un calcul

cs_philpas Messages postés 77 Date d'inscription lundi 17 octobre 2005 Statut Membre Dernière intervention 4 septembre 2008 - 16 févr. 2006 à 13:55
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 - 7 mars 2006 à 00:25
bonjour,
j'ai un soucis avec la réponse d'un résultat de calcul

j'écris

if Position_Courante.Z-Position_Courante.Y<Ecart_mini_Cassette then
begin
Message_Erreur(18,'');
end;

Position_courante.Z et Y sont des variables de type Real et Ecart_mini_Cassette est une constante égale à 125

A un moment de mon programme, j'ai (en visualisant les valeurs de position_courante) pour Z => 198.2 et pour Y => 73.2 soit en faisant la soustraction 198.2-73.2=125
Normalement le test que je fait (Z-Y<125) affiche mon message d'erreur que dans le cas où le résultat (Z-Y) est inférieur à 125 hors dans mon cas il m'affiche mon message d'erreur. Il me fait l'instruction comme si j'avais écrit (Z-Y<=125)
J'ai mis des parenthèses, mais ça ne change rien. Je peux imaginer que le résultat réel de l'opération (Z-Y) soit égale à 124.999999999....Etc... et qu'il m'affiche 125 lorsque je visualise la valeur par la procédure Evaluer. Mais même en multipliant les valeurs Y et Z par 10000000 pour voir leurs "valeurs exactes" (je pensais voir par exemple 1981999999 pour Z) et bien c'est pas le cas.
Comment dois je faire pour résoudre ce problème?

Merci
@+

17 réponses

Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
16 févr. 2006 à 14:30
Salut,

Change le type Real en Extended et ça fonctionne
pourquoi je ne sais pas encore je vais voir si je trouve pourquoi

@+
Cirec
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
16 févr. 2006 à 14:43
Salut,
voici ce que j'ai trouvé :

extrait de l'aide de Delphi :


Remarque: Le type Real48 sur six octets s'appelait Real dans les versions précédentes du Pascal Objet. Si vous recompilez dans Delphi du code utilisant ce type Real sur six octets ancienne manière, vous pouvez le changer en Real48. Vous pouvez également utiliser la directive de compilation {$REALCOMPATIBILITY ON} qui revient à l'interprétation de Real comme un type sur six octets.

Les remarques suivantes s'appliquent aux types réels fondamentaux.

<LI>Real48 est conservé pour la compatibilité ascendante. Comme son format de stockage n'est pas géré naturellement par l'architecture des processeurs Intel, ce type produit des performances plus mauvaises que les autres types à virgule flottante. Le type Real48 a été déprécié sur la plate-forme .NET. </LI>

<LI>Extended propose une meilleure précision que les autres types réels, mais il est moins portable. Evitez d'utiliser Extended si vous créez des fichiers de données qui doivent être partagés sur plusieurs plates-formes. </LI>

@+
Cirec
0
cs_philpas Messages postés 77 Date d'inscription lundi 17 octobre 2005 Statut Membre Dernière intervention 4 septembre 2008
16 févr. 2006 à 15:34
j'ai passé toute les déclarations de variable Real que j'avais en Extended et j'ai le même phénomène mais cette fois avec d'autres valeurs pour Y et Z mais dont la soustraction donne également 125.
Cela n'a pas résolu mon problème

dans l'aide de delphi 6 personnel j'ai trouvé ça:
Le type générique Real est équivalent, dans son implémentation actuelle, au type Double.


Type Etendue Chiffres significatifs Taille en octets
Real 5.0 x 10^–324 .. 1.7 x 10^308 15–16 8

@+
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
16 févr. 2006 à 15:38
Salut,
c'est vraiment bizarre ton problème
j'ai fait les testes de mon coté avant de poster et avec le type real j'obtient effectivement une erreur mais pas avec le type extended ???

@+
Cirec
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_philpas Messages postés 77 Date d'inscription lundi 17 octobre 2005 Statut Membre Dernière intervention 4 septembre 2008
16 févr. 2006 à 15:45
Comment je peux contourné ce problème? avec des fonctions arrondi? peut être avec RoundTo par exemple?

@+
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
16 févr. 2006 à 15:48
attend je me remet aux testes

@+
Cirec
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
16 févr. 2006 à 15:59
Bon fait ces deux testes stp et dis moi si le resultat est identique où si il diffère en fonction du type utilisé :

var
Form1: TForm1;
y, z : Real; // une fois avec y et z en Real et une fois avec y et z en Extended
Const ValeurDeControl = 125;
implementation


{$R *.DFM}


procedure TForm1.Button1Click(Sender: TObject);
Var MSg : String;
begin
z : = 198.2;
y := 73.2;
If z - y < ValeurDeControl Then Msg : = 'Erreur'
Else Msg := 'Ok';
ShowMessage(Msg);
end;

Si le resultat est identique je chercherai plus loin

@+
Cirec
0
cs_philpas Messages postés 77 Date d'inscription lundi 17 octobre 2005 Statut Membre Dernière intervention 4 septembre 2008
16 févr. 2006 à 16:14
alors résultat :
avec y et z Real : le message est erreur
avec y et z Extended : le message est Ok

donc là ça fonctionne. j'ai remis toutes mes déclarations Real dans mon programme en Extended. J'ai toujours le message d'erreur mais sur d'autres valeurs. J'ai pris les valeurs qui m'affiche le message Y-286.24 et Z -161.24 et j'ai testé ces valeurs avec ton programme test et là le résultat est différent (-161.24 - (-286.24)) = 125
j'ai avec y -286.24 et z -161.24
avec y et z Real : le message est erreur
avec y et z Extended : le message est erreur

donc Extended ne résoult pas le problème
@+
0
cs_philpas Messages postés 77 Date d'inscription lundi 17 octobre 2005 Statut Membre Dernière intervention 4 septembre 2008
16 févr. 2006 à 16:22
je rectifie une petite erreur j'ai écrit trop vite
j'ai avec y -286.24 et z -161.24
avec y et z Real : le message est Ok
avec y et z Extended : le message est erreur

@+
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
16 févr. 2006 à 16:25
Oui j'ai fait les même testes et j'ai déjà rectifier
bon j'ai essayer avec Currency à la place de Real et Extended et là les deux operations me donne Ok
Essaye ça et dis moi
Currency d'après l'aide est le type le plus précis

@+
Cirec
0
cs_philpas Messages postés 77 Date d'inscription lundi 17 octobre 2005 Statut Membre Dernière intervention 4 septembre 2008
16 févr. 2006 à 16:50
apparemment ça marche. Je verrais bien à l'usage si j'ai d'autre valeurs Y et Z qui provoque cette anomalie. C'est quand même bizarre que sur d'aussi petite valeur (z=-286.24 et y=-161.24) à 2 chiffres après la virgule, et que les intervalles de Real ou extended étant énorme, que le résultat ne soit pas bon.

@+
Merci
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
16 févr. 2006 à 16:56
suite de l'aide de Delphi :

Currency est un type de données à virgule fixe qui limite les erreurs d'arrondi dans les calculs monétaires. Il est stocké dans un entier sur 64 bits, les quatre chiffres les moins significatifs représentant implicitement les chiffres après la virgule. Quand il est combiné avec d'autres types réels dans des affectations et des expressions, les valeurs Currency sont automatiquement divisées ou multipliées par 10000.

@+
Cirec
0
cs_philpas Messages postés 77 Date d'inscription lundi 17 octobre 2005 Statut Membre Dernière intervention 4 septembre 2008
17 févr. 2006 à 10:05
Currency me résout des problèmes mais m'en crée d'autre. Je voulais transformé toute les déclarations Real en currency dans mon programme afin de ne plus rencontré le problème décris précédemment car j'ai beaucoup de test de type > et <. Mais j'utilise aussi beaucoup dans mon programme la conversion texte en nombre soit
Val(S; var V; var Code: Integer)
mais la variable V ne peut pas être de type Currency. Y a t-il d'autre fonction de convertion de texte en nombre et qui prendrait currency?

@+
0
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
17 févr. 2006 à 11:52
salut,

utilises la fonction strtofloat;

valeur:=strtofloat(chaine);



@+

jlen
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 34
17 févr. 2006 à 22:57
sur des calcul simple ne necessitant pas de gros chiffre, je vous conseil tout simplement d'utiliser le type Single (flottant signé 32 bits)

ensuite quand tu ecris :

Y - Z < 125

attention au signes!

-1 - -1 = 0
-1 + -1 = -2
-1 -1 = -2
-1 + 1 = 0

attention a la virgule!

(y - z) < 125.0

car ne pas oublier que

0.1 - 0.1 = 0.0 et non 0

je serais curieux de voir ton code...

La theorie c'est quand on sait tout, mais que rien ne fonctionne.
La pratique c'est quand tout fonctionne, mais que personne ne sait pourquoi.
<hr>
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
17 févr. 2006 à 23:02
Salut f0xi,
tu as vu l'exemple que je lui ai donner plus haut (mon 5 ème poste )


peux-tu m'éclairer sur ce type de problème c'est quand même étrange


@+

Cirec
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 34
7 mars 2006 à 00:25
alors bizarrement, et aprés plusieurs tests,

avec les types

Real : 125 <> 125
Double : 125 <> 125

par contre avec les types :

currency, single, comp et extended, pas de probleme 125 = 125 ...

pourquoi ?
je sais pas...

Extended propose une meilleure précision que les autres types réels, mais il est moins portable. Evitez d'utiliser Extended si vous créez des fichiers de données qui doivent être partagés sur plusieurs plates-formes.

Le type Comp est un type natif de l'architecture des processeurs Intel et représente un entier sur 64 bits. Il est néanmoins classé parmi les réels car il ne se comporte pas comme un type scalaire. Par exemple, il n'est pas possible d'incrémenter ou de décrémenter une valeur Comp. Comp est conservé uniquement pour la compatibilité ascendante. Utilisez le type Int64 pour de meilleures performances.

Currency est un type de données à virgule fixe qui limite les erreurs d'arrondi dans les calculs monétaires. Il est stocké dans un entier sur 64 bits, les quatre chiffres les moins significatifs représentant implicitement les chiffres après la virgule. Quand il est combiné avec d'autres types réels dans des affectations et des expressions, les valeurs Currency sont automatiquement divisées ou multipliées par 10000.

donc ... preference a Single ou Currency qui sont plus precis que les autres et moins contraignant.

La theorie c'est quand on sait tout, mais que rien ne fonctionne.
La pratique c'est quand tout fonctionne, mais que personne ne sait pourquoi.
<hr>
0
Rejoignez-nous