Problème d'égalité avec OleDateTime

cs_palmipede Messages postés 8 Date d'inscription dimanche 25 mars 2007 Statut Membre Dernière intervention 19 octobre 2010 - 15 oct. 2010 à 14:32
cs_palmipede Messages postés 8 Date d'inscription dimanche 25 mars 2007 Statut Membre Dernière intervention 19 octobre 2010 - 19 oct. 2010 à 09:40
Bonjour à tous !

Depuis assez longtemps, j'ai un soucis avec l'opérateur d'égalité (==) des OleDateTime qui donne parfois un résultat erroné. Le problème survient aussi avec les opérateur != <= et >= qui font appel à ==.

A certains moments, lors de la comparaison de dates, des décimales insignifiantes s'ajoute sur le double utilisé comme stockage par un des 2 objets comparés, ce qui ne change pas la date qu'il contient, mais qui fausse le résultat de la comparaison. J'ai repéré ce même problème à d'autre endroit lorsque l'on utilise des doubles transmis par valeurs dans les méthodes.

Première question, quelqu'un a t'il déja eu ce même problème ? Peut-on le résoudre par une option de compile, la désactivation d'une optimisation ou autre ?

Si le problème ne peut pas être résolu, il va falloir que je modifie/remplace l'objet datetime et datetimespan que j'utilise pour être sûr de mes comparaisons.

Description de la solution sur laquelle j'ai le problème :
Une application MFC sous Visual C++ 2008 comprenant environ 120000 lignes de codes, en 9 projets dll et un projet exécutable faisant appel à ces dll. J'utilise les OleDateTime et OleDateTimeSpan à de multiples endroits dans chacun des projets (après rapide recherche, l'identifier COleDateTime apparaît plus de 1700 fois).

Je ne peux pas remplacer simplement les classes oledateTime et oledateTimeSpan par d'autres classes équivalentes sans faire de grosses modifications au projet. J'aimerais limiter au maximum l'impact de ces modifications sur les sources du projet (Je préfèrerais ne pas être obligé d'ajouter un include sur chaque .h et ne pas avoir à remplacer le nom des classes à chaque endroit).

La solution que j'avais mise en place et qui fonctionnait ne me plaît pas : elle consistait à surdéfinir les classes COleDateTime et COleDateTimeSpan, à remplacer leur opérateur ==, et à appeler mes classe au lieu des classes de base. Le problème est que les modifications touchent énormément de fichiers source, et que les opérateurs == des classes de base ne sont pas définis virtuels.
La solution pouvait être améliorée en ajoutant ces lignes à chaque .h du projet :
#include "MyTime.h"
#define COleDateTime CMyOleDateTime
#define COleDateTimeSpan CMyOleDateTimeSpan
ce qui limite l'impact des modification dans le code mais qui m'oblige à modifier là encore tous les fichiers .h.

Une autre de mes idées étais de redéfinir des classes en recopiant le code des classes de base et en modifiant les opérateurs ==, ce qui du point de vue rapidité d'exécution me semble mieux, mais je perds le lien avec les classes de bases si elles évolue et les modifications touchent aussi énormément de fichiers sources.

N'y aurait-il pas une solution pour que ces lignes de code soit définies dans ma solution ou même sur chacun des projets et aient une portée sur tous mes fichiers sources ? (ce qui me permettrais de ne pas modifier tous les fichiers et qui éviterais par la même occasion qu'un autre développeur utilise par mégarde COleDateTime/Span au lieu de mes classes)

Merci d'avance
J'ai pas mal usé mon clavier pour décrire le problème, désolé si j'use vos yeux quand vous le lisez

Palmipede.

4 réponses

cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
16 oct. 2010 à 13:27
Salut,

Comme un double est utilisé pour le stockage, on a le même souci que pour la comparaison de double, ou plus généralement, le même souci que lors de comparaison de nombres à virgule flottante. On ne doit pas utiliser ==. Plus d'info via google, genre ici.

Peut être peux tu conserver les classes de base, mais remplacer l'utilisation des opérateurs par des appels à des fonctions statiques de ton cru (Mais c'est lourd aussi j'imagine).
0
cs_palmipede Messages postés 8 Date d'inscription dimanche 25 mars 2007 Statut Membre Dernière intervention 19 octobre 2010
18 oct. 2010 à 10:22
Ok, donc c'est bien un problème au niveau du type de données... Malheureusement après recherches via google comme tu me l'a conseillé, aucune solution simple pour résoudre ce problème de comparaison de flottants.
Parfois je me demande à quoi pensaient les développeurs de chez Microsoft quand ils ont basé leur comparaisons de dates sur des comparaisons de flottants
Des int de 32 ou 64 bit n'auraient pas posé ce genre de problème

Et pour la deuxième partie de ma question, quelqu'un aurait-il une idée ?
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
18 oct. 2010 à 10:31
Pour la comparaison de flottant, on utilise un "epsilon", une très petite valeur. Si la différence entre deux flottant est inférieure à cette valeur, alors les flottants sont égaux.

Quelque chose comme if (fabs(f1 - f2) < epsilon) { printf("égaux"); }

La solution du lien de mon précédent message est cependant probablement plus optimisée (Pas d'appel de fonction).
0
cs_palmipede Messages postés 8 Date d'inscription dimanche 25 mars 2007 Statut Membre Dernière intervention 19 octobre 2010
19 oct. 2010 à 09:40
Ok, merci ^^
Le seul problème du Epsilon c'est la question de savoir sur quelle base tu défini ton Epsilon ? Tu le défini en fonction d'un sizeof de tes float/double pour déterminer l'erreur qui risque de les différencier ? ou bien en fonction d'une utilisation particulière du float/double ? (Je suis vraiment allergique aux valeurs en dur dans le code )
J'ai trouvé une classe mieux faite que les OleDateTime qui travail sur de l'entier au lieu des double (et qui n'a donc pas besoin de Epsilon lors des comparaisons), mon problème c'est de l'inclure partout sans trop modifier de code : d'où la seconde partie de ma question, define or not define ? Où placer l'inclusion de mon nouvel objet ? Est-il possible de l'inclure une seule fois pour toute ma solution ?
0
Rejoignez-nous