madmax1
madmax1

Reputation: 267

Floating point formats and isinf()

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:

Upvotes: 4

Views: 539

Answers (1)

Pascal Cuoq
Pascal Cuoq

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

Related Questions