Reputation: 267
I am currently dealing with floating point values in C++. Consider the following c++ snippet:
#include <cmath>
#include <cstring>
#include <iostream>
int main() {
long double num;
// Set num to a large, valid, floating point value
memset(&num, 0xcc, sizeof(num));
std::cout << "num = " << num << std::endl;
std::cout << "isinf(num) = " << isinf(num) << std::endl;
std::cout << "std::isinf(num) = " << std::isinf(num) << std::endl;
return 0;
}
According to Wikipedia, this creates an 80 bit extended precision floating point value, as I am using GCC on an x86 machine. The floating point value is therefore 0xcccc cccc cccc cccc cccc
and should be valid value.
Interestingly, the output is as follows:
num = -4.77987e+986
isinf(num) = 1
std::isinf(num) = 0
This makes me wonder:
isinf
and std::isinf
differently? And which one is to be trusted?-std=c++98
, i still get the same behavior. Shouldn't std::isinf
not even be defined in that case?Upvotes: 4
Views: 539
Reputation: 80325
isinf
, the function from cmath
intended for compatibility with the C language, takes a double
. Your long double
argument is silently converted to double
when passed to that function. The conversion to double
produces +inf
according to the floating-point rounding rules (any number larger than a limit itself slightly larger than DBL_MAX
gets rounded to +inf
).
By contrast, std::isinf
is overloaded and can take a long double
. When you pass it a long double
, the argument is not converted and std::isinf
can tell that it is not infinite.
To try to answer your other questions:
it is a small detail whether isinf
is a macro or a function. Knowing that it is a macro is only convenient for programmers who want to #undef
it. Whether it is a function or is guaranteed to be a macro, it behaves the same (converts its argument to double
).
DBL_MAX
and LDBL_MAX
from float.h
/cfloat
are sufficiently indicative to distinguish between IEEE 754 double-precision (64-bit format) or the extended 80-bit format. You can also look at additional macros, such as DBL_MANT_DIG
and LDBL_MANT_DIG
, if you want to be certain that your code recognizes, say, quad-precision in 20 years when widespread processors implement it (this is not the case in 2017). It is not recommended to look at sizeof(long double)
because this value can be 10, 12 or 16 for the 80-bit floating-point format depending on how much the compiler pads it, and the value 16 could also indicate quad-precision.
Upvotes: 6