8
votes

Est-ce une bonne idée de comparer Double.MaxValue pour l'égalité?

Même question peut être demandé au flotteur ... ou de Minvalue.

Je pense à l'utiliser comme valeur spéciale. Vais-je voir des bugs en raison de la précision? Je ne m'attends pas à faire de l'arithmétique avec ces chiffres, je viens de les mettre et c'est ça.

Clarification: J'utilise cela pour une valeur sentinelle.

Est-ce quelque chose qui est décrit dans une spécification C #?


4 commentaires

Je sais que c'est une sorte de duplicata des autres, en fonction de la théorie de la comparaison des numéros de points flottants. Je dis que si le double est plus grand que Maxvalue, il déborde, donc à moins que vous testez pour voir si vous êtes sur le point de déborder, alors je pense que cela va être préférable de tester une limite de précision sûre.


Pouvez-vous ajouter plus de détails à votre question? Je ne comprends pas ce que vous voulez comparer.


@ROFLCOPTR: Ajout de certains détails.


FWIW, il y a une situation où j'utilise Maxvalue / Minvalue de cette façon. Souvent. Lors de la recherche d'un minimum d'un ensemble, je commence avec Maxvalue. Donc, je n'ai pas besoin de crud supplémentaire pour que le ministère a commencé, ni un test supplémentaire avec la boucle. float mina = flotteur.maxvalue; foreach (flotter a ...) si (un Je fais cela quand j'ai besoin de suivre Autres valeurs associées à celles A s.


5 Réponses :


1
votes

Utiliser des "valeurs spéciales" est généralement une mauvaise pratique. Je préférerais utiliser un objet avec une sorte de code d'état, puis un double (/ flotteur / autre) peuplé que si le statut est non exceptionnel.

public class CalcNumber
{
    public CalcNumberStatus Status {get; private set;}
    public double Value {get; private set;}


    public CalcNumber(double value)
    {
        Status = CalcNumberStatus.Normal;
        Value = value;
    }

    public CalcNumber(CalcNumberStatus status)
    {
        if(status == CalcNumberStatus.Normal)
        {
            throw new Exception("Cannot create a normal CalcNumber without a value");
        }
        Status = status;
        Value = 0;
    }
}
public enum CalcNumberStatus 
{
    Normal,
    Error
}


1 commentaires

J'ai des limitations auto-imposées (sans doute) au sein de Codegen que l'entreprise utilise. Je dois rester au type primitif ici.



3
votes

Si vous comparez double.MAXValue à double.MAXValue , oui, ils seront les mêmes. La représentation binaire est identique, il n'y aura pas de problème. Si, d'autre part, vous essayez quelque chose comme: xxx

alors oui, vous commencerez probablement à voir des problèmes de précision étranges apparaissent.

Les constantes spéciales sont des constantes spéciales qui ne peut pas être comparé à eux-mêmes. Autre chose est le jeu juste.

  • NAN
  • négatifInfinity
  • positifInfinity

5 commentaires

J'ai lu quelque part que c'est une mauvaise idée de comparer l'infini (positif ou négatif) avec ==. C'est pourquoi le double a des fonctions utilitaires pour ceux-ci.


Ah oui j'ai oublié celles-ci. Il en va de même pour eux comme NaN.


J'ai mis à jour cela pour refléter les constantes qui nécessitent des tests spéciaux.


@Chris: C'est Math.PI que vous atteigniez, ou 3.1416, si bien arrondi. Ne revleurez pas le problème cependant :)


@Gregc je sais ce que j'ai écrit. Je ne veux pas tous ces autres chiffres, PI est trop précis. Oui, je l'ai dit. Trop précis.



0
votes

Je ne pense pas que ce devrait être un problème. Je n'ai pas d'explication technique mais j'ai utilisé Maxvalue ou Minvalue pour des comparaisons à plusieurs reprises et ce n'est jamais un problème.


0 commentaires

11
votes

Cela dépend de la façon dont vous l'utilisez.

Si vous utilisez double.MAXValue comme une valeur de jeton ou de sentinelle contenant une sémantique spéciale, alors oui, c'est juste un modèle de bits que vous comparez contre. Par exemple, vous pouvez utiliser double.MAXValue pour indiquer une valeur "non initialisée" ou "inconnue". Il existe d'autres moyens de le faire (par exemple avec le nullable double? ), mais en utilisant double.MAXValue est également raisonnable en supposant que la valeur ne se produise pas naturellement dans votre domaine.

Si vous avez une valeur de arbitraire double , et que vous souhaitez voir si c'est "égal" à double.MAXValue , alors vous voulez voir si Les chiffres sont dans une certaine petite gamme (Epsilon) l'une de l'autre puisque une certaine précision aurait pu être perdue lors de l'informatique de votre autre valeur double . La question à savoir ici est avec des valeurs qui vont au-delà de double.MAXValue , créant une situation de débordement.


0 commentaires

1
votes

Si vous voulez une valeur "spéciale", ma suggestion serait d'utiliser Nullable à la place:

double? val = ...;

if(val.HasValue)
    // do something with val.Value


4 commentaires

J'ai utilisé NULL, NAN, positif et négatif INF.


@Gregc: Uhoh. Temps pour les nombres complexes, mon ami


@Gregc quelque chose est définitivement tort avec votre conception. Avez-vous déjà entendu parler d'exceptions?


Je sais que. Demain je vais parler au gars qui écrit notre codegen. :)