std::numeri...gnaling_NaN(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… NAME πŸ’…

std::numeric_limits::signaling_NaN β€” bestie, it's literally std::numeric_limits::signaling_NaN, that's the whole name, we're starting strong ✨

(also hi, this is the std::numeri...gnaling_NaN(3) page from the C++ Standard Library β€” the keyword got a little squished in the terminal, she's fine, she's just dramatic πŸŽ€)


✨ Synopsis ✨

static T signaling_NaN() throw();             (until C++11)
static constexpr T signaling_NaN() noexcept;  (since C++11)

Okay so picture this: this thing returns the special value known as "signaling not-a-number", exactly as your floating-point type T represents it. Obsessed. πŸ’–

But heads up β€” it's only meaningful if std::numeric_limits<T>::has_signaling_NaN == true. Like, if your type can't do signaling NaNs, don't come crying to this function, she can't help you 😭

Now for the nerd lore, and honestly it ate: in IEEE 754 β€” the most common binary representation of floating-point numbers, iykyk β€” any value where all bits of the exponent are set and at least one bit of the fraction is set represents a NaN. Slay.

It is implementation-defined which values of the fraction represent quiet vs. signaling NaNs, and also whether the sign bit is even meaningful. So like... the vibes vary by compiler, no cap. πŸ¦‹


πŸŽ€ Return value πŸŽ€

Here's the whole lineup, no skipping, I promised:

girl, but as a list:
  • T β€” std::numeric_limits<T>::signaling_NaN()
  • /* non-specialized */ β€” T()
  • bool β€” false
  • char β€” 0
  • signed char β€” 0
  • unsigned char β€” 0
  • wchar_t β€” 0
  • char8_t (since C++20) β€” 0
  • char16_t (since C++11) β€” 0
  • char32_t (since C++11) β€” 0
  • short β€” 0
  • unsigned short β€” 0
  • int β€” 0
  • unsigned int β€” 0
  • long β€” 0
  • unsigned long β€” 0
  • long long (since C++11) β€” 0
  • unsigned long long (since C++11) β€” 0
  • float β€” implementation-defined (may be FLT_SNAN)
  • double β€” implementation-defined (may be DBL_SNAN)
  • long double β€” implementation-defined (may be LDBL_SNAN)

Look at all those zeroes. Not a single one of them is having a main character moment and honestly? Respect. 🫢


πŸ¦‹ Notes πŸ¦‹

  • A NaN never compares equal to itself. Not even to itself. Not even once. The self-love journey is not going well πŸ’€
  • Copying a NaN is not required, by IEEE-754, to preserve its bit representation (sign and payload) β€” though most implementations do. So like, usually fine, but don't @ me if it isn't. πŸ™ˆ
  • When a signaling NaN is used as an argument to an arithmetic expression, the appropriate floating-point exception may be raised, and the NaN gets "quieted" β€” meaning the expression returns a quiet NaN. She's been through something and she's calmer now. 🌸

πŸ”₯ Example πŸ”₯

Demonstrates the use of a signaling NaN to raise a floating-point exception. It's giving lab demo, it's giving pedagogy, we love her:

// Run this code

#include <cfenv>
#include <iostream>
#include <limits>

#pragma STDC_FENV_ACCESS on

void show_fe_exceptions()
{
    int n = std::fetestexcept(FE_ALL_EXCEPT);

    if (n & FE_INVALID)
        std::cout << "FE_INVALID is raised\n";
    else if (n == 0)
        std::cout << "no exceptions are raised\n";

    std::feclearexcept(FE_ALL_EXCEPT);
}

int main()
{
    double snan = std::numeric_limits<double>::signaling_NaN();
    std::cout << "After sNaN was obtained, ";
    show_fe_exceptions();

    double qnan = snan * 2.0;
    std::cout << "After sNaN was multiplied by 2, ";
    show_fe_exceptions();

    double qnan2 = qnan * 2.0;
    std::cout << "After the quieted NaN was multiplied by 2, ";
    show_fe_exceptions();

    std::cout << "The result is " << qnan2 << '\n';
}

⭐ Output ⭐

After sNaN was obtained, no exceptions are raised
After sNaN was multiplied by 2, FE_INVALID is raised
After the quieted NaN was multiplied by 2, no exceptions are raised
The result is nan

The way that nan is just sitting there at the end of the line. Iconic. Unbothered. Moisturized. 🧚


πŸ‘‘ See also πŸ‘‘

  • has_signaling_NaN β€” identifies floating-point types that can represent the special [static] value "signaling not-a-number" (NaN) β€” (public static member constant)
  • quiet_NaN β€” returns a quiet NaN value of the given floating-point type β€” [static] β€” (public static member function)
  • isnan (C++11) β€” checks if the given number is NaN β€” (function)

Real talk bestie: this page is from http://cppreference.com, dated 2024.06.10, and it's the std::numeri...gnaling_NaN(3) manual page πŸ’œ Go raise some floating-point exceptions responsibly, and drink water. Mwah! πŸ’…βœ¨
πŸ“¦ where this page comes from