In the c++ standard for floating pointer number, there is std::isgreater
for greater comparison, and std::isless
for less comparison, so why is there not a std::isequal
for equality comparison? Is there a safe and accurate way to check if a double
variable is equal to the DBL_MAX
constants defined by the standard? The reason we try to do this is we are accessing data through service protocol, and it defines a double field when no data is available it will send DBL_MAX
, so in our client code when it's DBL_MAX
we need to skip it, and anything else we need to process it.

- 13,238
- 8
- 62
- 100
-
4Because comparing floating point numbers for equality doesn't work out well, because they are subject to rounding errors. I think [this question](https://stackoverflow.com/questions/17333/what-is-the-most-effective-way-for-float-and-double-comparison) will help you. – Lukas-T Dec 10 '19 at 08:31
-
1Please see the list of related question to the right of your question, many of them will explain why floating point equality comparisons are very often not possible. – Some programmer dude Dec 10 '19 at 08:31
-
1What practical use is there for comparing inherently inaccurate numbers for equality? Especially `DBL_MAX`, which is an absurdly huge number with an absurdly low precision? If you tell us what exactly you're trying to do, maybe we can find a better solution to achieve that. – Blaze Dec 10 '19 at 08:33
-
1Why not `a==b`? – ALX23z Dec 10 '19 at 08:34
-
1@ALX23z i read that `==` operator does not work for flats/doubles. – fluter Dec 10 '19 at 08:54
-
If you know that it adheres to IEEE 754 you could do a check like `d > 1.0e300` (assuming that no valid number will be this big). – Blaze Dec 10 '19 at 09:02
-
3@fluter If you "read somewhere" that _"operator `==` does not work for `float`/`double`"_ then you need to do more reading, as that's not true. In fact, it's outright dangerous. And a hypothetical `std::isequal` would not fix the problem. Please see https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html. – Max Langhof Dec 10 '19 at 11:55
-
@churill: No, “Because comparing floating point numbers for equality doesn't work out well” is not the reason there is a `std::isless` and a `std::isgreater` but not a `std::isequal`. – Eric Postpischil Dec 10 '19 at 13:00
-
@fluter the operation `==` works. Only it isn't too useful. Insignificant change of the floating nember results in inequality. – ALX23z Dec 10 '19 at 14:22
3 Answers
The interest of isgreater
, isless
, isgreaterequal
, islessequal
compared to >
, <
, >=
and <=
is that they do not raise FE_INVALID (a floating point exception, these are different beasts than C++ exceptions and are not mapped to C++ exceptions) when comparing with a NaN while the operators do.
As ==
do not raise a FP exception, there is no need of an additional functionality which does.
Note that there is also islessgreater
and isunordered
.
If you are not considering NaN or not testing the floating point exception there is no need to worry about these functions.
Considering equality comparison ==
is what to use if you want to check that the values are the same (ignoring the issues related to signed 0 and NaN). Depending on how you are reaching these values, it is sometimes useful to consider an approximate equality comparison -- but using one systematically is not recommended, for instance such approximate equality is probably not transitive.
In your context of a network protocol, you have to consider how the data is serialized. If the serialization is defined as binary, you can probably reconstruct the exact value and thus ==
is what you want so compare against DBL_MAX
(for other values, check what is specified for signed 0 and NaN an know that there are signalling and quiet NaN are represented by different bit patterns although IEEE 754-2008 recommend now one of them). If the representation is decimal, you'll have to check if the representation is precise enough for the DBL_MAX
value be reconstructable (and pay attention to rounding modes).
Note that I'd have considered a NaN for representing the no data available case instead of using a potentially valid value.

- 51,233
- 8
- 91
- 143
Is there a safe and accurate way to check if a double variable is equal to the
DBL_MAX
constants defined by the standard?
When you obtain a floating point number as a result of evaluating some expression, then ==
comparison doesn't make sense in most cases due to finite precision and rounding errors. However, if you first set a floating point variable to some value, then you can compare it to that value using ==
(with some exceptions like positive and negative zeros).
For example:
double v = std::numeric_limits<double>::max();
{ conditional assignment to v of a non-double-max value }
if (v != std::numeric_limits<double>::max())
process(v);
std::numeric_limits<double>::max()
is exactly representable as double
(it is double
), so this comparison should be safe and should never yield true
unless v
was reassigned.

- 25,259
- 5
- 41
- 83
-
I'm curious why < or > would make sense then, because there might be accumulated errors on both operands leading to a false result, much like for ==. Even extra precision (like 80 bit registers) can lead to catastrophic < results for trivial cases. For example since IEEE754 double 1/10 is rounded upper, long double x = 1.0/10.0; might well be considered < double y = 1.0/10.0; So < and > are also broken and make no sense if we follow that logic... – aka.nice Dec 10 '19 at 10:08
-
1@aka.nice `std::isless` / `std::isgreater` serve different purpose: they [suppress floating-point exceptions](https://en.cppreference.com/w/cpp/numeric/math/isgreater#Notes). The problem of precision with all comparisons is still there. They all are "broken" in that sense. – Evg Dec 10 '19 at 10:15
-
so you agree that the right answer is about not raising exception rather than not making sense because of inaccuracy, like AProgrammer explained. – aka.nice Dec 10 '19 at 10:33
-
@aka.nice, I agree. But OP asked two questions. The first one is about `std::isgreater` and `std::isless`. The second one is about how to detect `DBL_MAX`. **AProgrammer** answered the first one, I answered the second one. – Evg Dec 10 '19 at 10:40
-
OK, I understand your answer better now. But we do not know the protocol used, if it is an ASCII decimal value that is passed thru, it will have to be decoded, and those computations require some guaranty too... – aka.nice Dec 10 '19 at 10:49
-
-
@EricPostpischil, I do not claim they have. I do not even mention `std:isless` and `std::isgreater` in my answer. I answer the second part of OP's question about checking for `DBL_MAX`. – Evg Dec 10 '19 at 13:00
-
@Evg: The question asks why there is not a `std::isequal`, and the answer is due to exception properties and not due to the rounding behaviors that this answer mentions. It has nothing to do with whether `==` “makes sense” “due to finite precision and rounding errors”. – Eric Postpischil Dec 10 '19 at 13:02
-
@EricPostpischil, the second part of the question is: "Is there a safe and accurate way to check if a double variable is equal to the `DBL_MAX` constants defined by the standard?" It has nothing to do with exceptions and `std:is_less`. You can do it using `==`. – Evg Dec 10 '19 at 13:04
-
I will modify my “This answer is wrong” to “This answer misses the point.” Nonetheless, it is not a helpful answer. – Eric Postpischil Dec 10 '19 at 13:07
-
@EricPostpischil, it follows from the question that OP's final goal is to check for `DBL_MAX` value ("is there a safe and accurate way", "we need to skip it"). My answer explains how to do it. I don't see how it is not helpful and how knowing about fp exceptions can be helpful to perform that check. – Evg Dec 10 '19 at 13:10
-
@Evg: This answer does not mention floating-point exceptions at all, so it does not help the reader know about floating-point exceptions. That is how it is missing the point: The question asks about why `std::isless` and `std::isgreater` are provided and `std::isequal` is not, and the answer is they exist to provide operations which do not generate floating-point exceptions, and `std::isequal` is not needed because `==` already provides that operation without generating floating-point exceptions. None of that is mentioned in this answer. – Eric Postpischil Dec 10 '19 at 13:15
-
@EricPostpischil, the question has two parts in it. It also asks how to check for `DBL_MAX`. The answer about fp exceptions does not address this part of the question at all. I admit that my answer is incomplete. But it does address the question about `DBL_MAX` value - and this is the real problem OP is trying to solve. – Evg Dec 10 '19 at 13:22
Equal function between to floating point have no sense, because the floating point numbers have rounding.
So if you want compare 2 floating point numbers for equality the best way is to declare a significant epsilon(error) for your comparison and then verify that the first number is in around the second.
To do this you can verify if first number is greater than second number minus epsilon and the first number is lower than the second number plus epsilon. Ex.
if ( first > second - epsilon && first < second + epsilon ){
//The numbers are equal
}else{
//The numbers are not equal
}

- 3,381
- 2
- 15
- 35
-
2
-
Yes he can compare if the 2 numbers are equal to DBL_MAX, but this is possible only if no operations are done since the initialization. However the correct espression is `first == second == DBL_MAX` – Zig Razor Dec 10 '19 at 10:12
-
5Although approximate equality tests are sometimes useful, please **don't** recommend them as a default replacement for equality as they are missing important property of equality such as transitivity. – AProgrammer Dec 10 '19 at 10:23
-
Yes, is logic that the transitivity property is lost when you apply this comparison, but in any case the transitivity property is lost already in the rounding process of the number... is only question of precision. So transitivity property is maintained to less than a precision or up to a certain decimal place. – Zig Razor Dec 10 '19 at 10:32
-
2Evg pointed out that, when `first = second = DBL_MAX`, this function will return false, even though the numbers are equal in every sense. The same happens for any double larger than your chosen `1/epsilon` - you will never get equality as `second - epsilon == second == first` and `second + epsilon == second == first`, so both `>` and `<` will yield `false`. – Max Langhof Dec 10 '19 at 11:53