2009-10-30 9 views
19

Le code suivant en C# ne fonctionne pas:Quelle est la meilleure façon de comparer Double et Int?

int iValue = 0; 
double dValue = 0.0; 

bool isEqual = iValue.Equals(dValue); 

Alors, la question: quelle est la meilleure façon de comparer Double et Int?

+0

Voir la question connexe: Konamiman

+0

[Quelle est la méthode la plus efficace pour les comparaisons flottantes et les doubles comparaisons?] (Http: // stackoverflow.com/q/17333/995714) –

Répondre

44

Vous ne pouvez vraiment pas comparer les valeurs à virgule flottante et intégrale de manière naïve; en particulier, car il y a le classique floating pointrepresentation challenges. Ce que vous pouvez faire est de soustraire l'un de l'autre et voir si la différence entre eux est inférieure à une certaine précision que vous aimez, comme ceci:

int iValue = 0; 
double dValue = 0.0; 

var diff = Math.Abs(dvalue - iValue); 
if(diff < 0.0000001) // need some min threshold to compare floating points 
    return true; // items equal 

Il faut vraiment définir pour vous-même ce que equality signifie pour vous . Par exemple, vous souhaiterez peut-être arrondir une valeur à virgule flottante vers l'entier le plus proche, de sorte que 3,999999981 soit égal à 4 ou que vous souhaitiez tronquer la valeur pour qu'elle soit effectivement 3. Tout dépend de ce que vous Essayons de réaliser.

EDIT: Notez que j'ai choisi 0,0000001 comme une valeur de seuil par exemple ... vous devez décider par vous-même ce que la précision est suffisante pour la comparaison. Il suffit de réaliser que vous devez être dans les limites normales de représentation de double qui, je crois, est défini comme Double.Espilon.

+0

Ceci est une bonne solution au problème que j'ai mentionné. Pour plus de précision (seulement quand c'est nécessaire), n'utilisez que des entiers, comme je l'ai suggéré dans ma réponse. –

+0

Serait-il préférable de comparer avec la constante epsilon définie par le système (voir ici http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx) au lieu d'une valeur codée en dur comme 0.0000001? NB Je n'ai jamais codé C# (juste C++) mais je suppose que le même principe s'applique – pxb

+1

Je mentionne cela dans l'édition de ma réponse. Epsilon peut ou peut ne pas être un bon choix en fonction de la précision de l'OP dans son code. – LBushkin

1

Cela dépend vraiment de ce que vous considérez comme "égal". Si vous voulez que votre comparaison retourne true si et seulement si la double correspond exactement à la valeur entière (ie n'a pas de composante fractionnaire), vous devez jeter votre int à un double pour faire la comparaison:

bool isEqual = (double)iValue == dValue; 

Si quelque chose comme 1.1 serait considéré comme égal à 1, vous pouvez soit lancer le double à un int (si vous voulez ignorer complètement le composant fractionnaire) ou arrondir le double si vous voulez dire 1.9 à égaler 2.

+0

Attention à l'arrondissement, cependant. Beaucoup de gens semblent surpris quand 2,5 tours à 2. – Joey

+0

@Joey Il est assez trivial d'écrire votre propre code d'arrondi pour avoir le comportement que vous voulez si les trois intégrés ne répondent pas à vos besoins. – Casey

3

C'est une très mauvaise idée comparer des entiers et des nombres à virgule flottante pour l'égalité dans n'importe quelle langue. Cela fonctionne pour des cas très simples, mais après que vous ayez fait des calculs, la probabilité que le programme fasse ce que vous voulez diminuerait considérablement.

Il s'agit de la façon dont les nombres à virgule flottante sont stockés sur un système numérique binaire.

Si vous êtes très sûr de vouloir l'utiliser, créez une classe pour vous approprier des fractions. utilise un int pour maintenir le nombre entier, et un autre int pour maintenir la fraction.

0

De nos jours, à peu près la seule fois que l'on doit comparer les valeurs des types double et soit integer ou long pour l'égalité stricte est quand, pour une raison quelconque, on est coincé stocker ou passer des quantités intégrales sous forme de valeurs à virgule flottante et les besoins ultérieurs pour les reconvertir. Dans la plupart des cas, cette conversion peut être facilement réalisée en convertissant le type intégral en double, puis en comparant le résultat de cette distribution. Notez que la conversion de long à double peut être imprécise si le nombre est en dehors de la plage ± 2 . Néanmoins, dans les jours précédant la disponibilité de long 64 bits, double était un type de stockage pratique pour les quantités entières qui étaient trop grandes pour un int 32 bits mais suffisamment petites pour être traitées par double.

Notez que la conversion d'un long-double et puis en faisant la comparaison donnera un résultat « égal » si la valeur nominale de l'double ne correspond pas exactement à la valeur long, mais représente le plus proche possible double à cette valeur. Ce comportement est logique si l'on reconnaît que les types à virgule flottante ne représentent pas réellement une seule valeur précise, mais plutôt une plage de valeurs. Où Double.Epsilon est la valeur la plus basse possible pour Double.

2
double val1 = 0; 
double val2 = 0.0; 
if((val1 - Double.Epsilon) < 0) 
{ 
    // Put your code here 
} 

     OR 

if((val2 - Double.Epsilon) < 0) 
{ 
    // Put your code here 
} 

Questions connexes