Is it a good idea to compare double.MaxValue for equality?
Asked Answered
S

5

8

Same question can be asked of float... or of MinValue.

I am thinking of using it as a special value. Will i see bugs due to precision? I don't expect to do arithmetic with these numbers, just set them and that's it.

Clarification: I am using this for a sentinel value.

Is it something that's described in a C# spec?

Situla answered 21/4, 2011 at 22:10 Comment(4)
I know this is sort of a duplicate of the others, based on the theory of comparison of floating point numbers. I say that if the double is larger than MaxValue then it will overflow, so unless you're testing to see if you're about to overflow, then I think it's going to be better to test to a safe limit of precision.Luminescence
Can you add further details to your question? I don't understand what you want to compare.Cockalorum
@Roflcoptr: added some details.Situla
FWIW, there is one situation where I use MaxValue/MinValue this way. Frequently. When finding a minimum of a set, I start with MaxValue. So I don't need extra crud to get the min-finder started, nor an extra test w/i the loop. float minA = float.MaxValue; foreach (float a ...) if (a < minA){ minA = a; ... } I do this when I need to track other values that are associated with those as.Bulgaria
G
12

It depends on how you use it.

If you're using double.MaxValue as a token or sentinel value that has special semantics, then yes, it's just a bit pattern that you're comparing against. For example, you could use double.MaxValue to indicate an "uninitialized" or "unknown" value. There are other ways to do this (e.g. with the nullable double?), but using double.MaxValue is also reasonable assuming the value doesn't naturally occur in your domain.

If you have some arbitrary double value, though, and you want to see if it's "equal" to double.MaxValue, then you'll want to see if the numbers are within some small range (epsilon) of each other since some precision could've been lost when computing your other double value. The issue to be aware of here is with values that go beyond double.MaxValue, creating an overflow situation.

Gavial answered 21/4, 2011 at 22:19 Comment(0)
W
3

If you compare double.MaxValue to double.MaxValue, yes they will be the same. The binary representation is identical, there won't be a problem. If, on the other hand, you try something like:

double myDouble = (double.MaxValue - 3.1415) / 2;
if((myDouble * 2) + 3.1415 == double.MaxValue)
{
    ...
}

then yes you'll probably start seeing weird precision issues pop up.

The following are special constants that can't be compared to themselves. Anything else is fair game.

  • NaN
  • NegativeInfinity
  • PositiveInfinity
Woolgrower answered 21/4, 2011 at 22:18 Comment(5)
I've read somewhere that it's a bad idea to compare infinity (either positive or negative) with ==. That's why double has utility functions for those.Geostatic
Ah yes I forgot about those. The same applies for them as NaN.Woolgrower
I've updated this to reflect the constants which require special tests.Woolgrower
@Chris: it's Math.PI that you were reaching for, or 3.1416, if properly rounded. Don't cloud up the issue though :)Situla
@Situla I know what I wrote. I don't want all those other digits, PI is too precise. Yes, I said it. Too precise.Woolgrower
E
1

Using "special values" is generally bad practice. I would prefer to use an object with some kind of status code, and then a double(/float/whatever) that is only populated if the status is non-exceptional.

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
}

You could even do some fancy operator overloading to make for easy conversion and arithmetic if you need to.

Regarding precision issues, since it sounds like you're not planning to do arithmetic on this number, so you shouldn't run into precision issues that prevent the equality check from working.

Elevation answered 21/4, 2011 at 22:18 Comment(1)
I have some (arguably) self-imposed limitations within codegen that the company uses. I have to stick to primitive type here.Situla
G
1

If you want a "special" value, my suggestion would be to use Nullable instead:

double? val = ...;

if(val.HasValue)
    // do something with val.Value
Geostatic answered 21/4, 2011 at 22:19 Comment(4)
I have used up null, NaN, Positive and Negative Inf.Situla
@GregC: Uhoh. Time for complex numbers, my friendBounce
@Situla Something is definitely wrong with your design. Ever heard of exceptions?Geostatic
I know that. Tomorrow I'll go talk to the guy who writes our codegen. :)Situla
D
0

I don't think it should be a problem. I don't have a technical explanation but I've used MaxValue or MinValue for comparisons many times and it's never been an issue.

Dayton answered 21/4, 2011 at 22:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.