When does NaN not propagate in C++? - c++

NaN propagates through "most" operations as described in NaN - Wikipedia.
I would like to know the operations which NaN does NOT propagate. For example, I'm coding in C++ and found that following code prints 1, which is not NaN.
const double result = std::pow(1, std::numeric_limits<double>::quiet_NaN());
std::cout << result << std::endl;
For std::powfunction, this behavior is described in std::pow - cppreference.com.
Could you share any other examples?

Here's an example demonstrating functions of NaN which return non-NaN. The list is in IEEE 754-2008, 9.2.1 Special values (there are some others functions, but they don't seem to be implemented in C++):
#include <cmath>
#include <limits>
#include <iostream>
int main()
{
const auto nan=std::numeric_limits<double>::quiet_NaN();
const auto inf=std::numeric_limits<double>::infinity();
std::cout << std::hypot(nan,inf) << '\n';
std::cout << std::hypot(inf,nan) << '\n';
std::cout << std::pow(nan, 0) << '\n';
std::cout << std::pow(1,nan) << '\n';
}
The output is:
inf
inf
1
1

std::pow is not really an operator in the sense that something like the multiplication in a * b is an operation. It's a function. And functions can have branches which can deal with a NaN as they please. Another similar std function is, in a sense, std::is_nan. This doesn't propagate NaN either: it returns a bool which is implicitly convertible to a numeric type:
std::is_nan(std::is_nan(a))
is false for any type a that allows the expression to compile. Other examples include std::fpclassify and std::isfinite. I particularly like std::fpclassify as an example since it has an int return type, so really it's no less of a numeric function than pow!
Note that the implicit conversion of NaN to bool is defined to be false true according to the accepted answer to this question, which is important. It allows !, &&, and || to work with an NaN. Finally, the expression separator operator , doesn't propagate NaN either, and an NaN on the unused branch of a ternary conditional operation is ignored.

The other case I would try is pow(0, NaN). If one has pow(0,0) == 1 then one should expect
pow(0, NaN) == 1
There is a rationale for this, and actually it is needed for consistent behavior.
Even though there is no IEEE standard dictating the behavior of all elementary functions with respect to NaN, there is a very basic rule:
If for all finite point numbers x including +inf and -inf (but excluding NaN) we have
f(const1, x) == const2
then (and only then) one also must return a non-NaN result
f(const1, NaN) == const2
#Long explanation
This is because NaN represents "undefined" or "any other numeric value from -inf .. inf". Why? Consider the prototypical example 0/0.
If one has the equation
b = a * x
and wants to solve for x. Clearly the solution is
x = b/a
Now if a == b == 0 then the original equation has infinitely many solutions, namely all finite numbers x. That's why NaN means "unspecified" and 0/0 == NaN. Now if an unspecified number (i.e. NaN) enters a function as an argument, it most often will cause an "unspecified" answer. The exception is where the output does not depend on the input, and in this case one should/must not return NaN.
Consider
pow(1, a/b)
This expression always evaluates to 1 for nonzero a and b, which makes sense from a mathematical point of view as the 1^x in a mathematical sense does not depend on x. So also numerically one would require that for a = 0 or b = 0 (and hence x=NaN) one also obtains 1.
So if one agrees upon the fact that
pow(1,-inf) = pow(1,inf) = 1
then one also has to define
pow(1,NaN) = 1
for consistent behavior. The same applies to pow(0,c) but also evaluation of a polynomial of degree zero should generate a non-NaN output on NaN input.
Note: this reasoning can be applied to any function, including the built-in operators.

Related

is assigning two doubles guaranteed to yield the same bitset patterns?

There are several posts here about floating point numbers and their nature. It is clear that comparing floats and doubles must always be done cautiously. Asking for equality has also been discussed and the recommendation is clearly to stay away from it.
But what if there is a direct assignement:
double a = 5.4;
double b = a;
assumg a is any non-NaN value - can a == b ever be false?
It seems that the answer is obviously no, yet I can't find any standard defining this behaviour in a C++ environment. IEEE-754 states that two floating point numbers with equal (non-NaN) bitset patterns are equal. Does it now mean that I can continue comparing my doubles this way without having to worry about maintainability? Do I have to worried about other compilers / operating systems and their implementation regarding these lines? Or maybe a compiler that optimizes some bits away and ruins their equality?
I wrote a little program that generates and compares non-NaN random doubles forever - until it finds a case where a == b yields false. Can I compile/run this code anywhere and anytime in the future without having to expect a halt? (ignoring endianness and assuming sign, exponent and mantissa bit sizes / positions stay the same).
#include <iostream>
#include <random>
struct double_content {
std::uint64_t mantissa : 52;
std::uint64_t exponent : 11;
std::uint64_t sign : 1;
};
static_assert(sizeof(double) == sizeof(double_content), "must be equal");
void set_double(double& n, std::uint64_t sign, std::uint64_t exponent, std::uint64_t mantissa) {
double_content convert;
memcpy(&convert, &n, sizeof(double));
convert.sign = sign;
convert.exponent = exponent;
convert.mantissa = mantissa;
memcpy(&n, &convert, sizeof(double_content));
}
void print_double(double& n) {
double_content convert;
memcpy(&convert, &n, sizeof(double));
std::cout << "sign: " << convert.sign << ", exponent: " << convert.exponent << ", mantissa: " << convert.mantissa << " --- " << n << '\n';
}
int main() {
std::random_device rd;
std::mt19937_64 engine(rd());
std::uniform_int_distribution<std::uint64_t> mantissa_distribution(0ull, (1ull << 52) - 1);
std::uniform_int_distribution<std::uint64_t> exponent_distribution(0ull, (1ull << 11) - 1);
std::uniform_int_distribution<std::uint64_t> sign_distribution(0ull, 1ull);
double a = 0.0;
double b = 0.0;
bool found = false;
while (!found){
auto sign = sign_distribution(engine);
auto exponent = exponent_distribution(engine);
auto mantissa = mantissa_distribution(engine);
//re-assign exponent for NaN cases
if (mantissa) {
while (exponent == (1ull << 11) - 1) {
exponent = exponent_distribution(engine);
}
}
//force -0.0 to be 0.0
if (mantissa == 0u && exponent == 0u) {
sign = 0u;
}
set_double(a, sign, exponent, mantissa);
b = a;
//here could be more (unmodifying) code to delay the next comparison
if (b != a) { //not equal!
print_double(a);
print_double(b);
found = true;
}
}
}
using Visual Studio Community 2017 Version 15.9.5
The C++ standard clearly specifies in [basic.types]#3:
For any trivially copyable type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a potentially-overlapping subobject, if the underlying bytes ([intro.memory]) making up obj1 are copied into obj2, obj2 shall subsequently hold the same value as obj1.
It gives this example:
T* t1p;
T* t2p;
// provided that t2p points to an initialized object ...
std::memcpy(t1p, t2p, sizeof(T));
// at this point, every subobject of trivially copyable type in *t1p contains
// the same value as the corresponding subobject in *t2p
The remaining question is what a value is. We find in [basic.fundamental]#12 (emphasis mine):
There are three floating-point types: float, double, and long double.
The type double provides at least as much precision as float, and the type long double provides at least as much precision as double.
The set of values of the type float is a subset of the set of values of the type double; the set of values of the type double is a subset of the set of values of the type long double.
The value representation of floating-point types is implementation-defined.
Since the C++ standard has no further requirements on how floating point values are represented, this is all you will find as guarantee from the standard, as assignment is only required to preserve values ([expr.ass]#2):
In simple assignment (=), the object referred to by the left operand is modified by replacing its value with the result of the right operand.
As you correctly observed, IEEE-754 requires that non-NaN, non-zero floats compare equal if and only if they have the same bit pattern. So if your compiler uses IEEE-754-compliant floats, you should find that assignment of non-NaN, non-zero floating point numbers preserves bit patterns.
And indeed, your code
double a = 5.4;
double b = a;
should never allow (a == b) to return false. But as soon as you replace 5.4 with a more complicated expression, most of this nicety vanishes. It's not the exact subject of the article, but https://randomascii.wordpress.com/2013/07/16/floating-point-determinism/ mentions several possible ways in which innocent looking code can yield different results (which breaks "identical to the bit pattern" assertions). In particular, you might be comparing an 80 bit intermediate result with a 64 bit rounded result, possibly yielding inequality.
There are some complications here. First, note that the title asks a different question than the question. The title asks:
is assigning two doubles guaranteed to yield the same bitset patterns?
while the question asks:
can a == b ever be false?
The first of these asks whether different bits might occur from an assignment (which could be due to either the assignment not recording the same value as its right operand or due to the assignment using a different bit pattern that represents the same value), while the second asks whether, whatever bits are written by an assignment, the stored value must compare equal to the operand.
In full generality, the answer to the first question is no. Using IEEE-754 binary floating-point formats, there is a one-to-one map between non-zero numeric values and their encodings in bit patterns. However, this admits several cases where an assignment could produce a different bit pattern:
The right operand is the IEEE-754 −0 entity, but +0 is stored. This is not a proper IEEE-754 operation, but C++ is not required to conform to IEEE 754. Both −0 and +0 represent mathematical zero and would satisfy C++ requirements for assignment, so a C++ implementation could do this.
IEEE-754 decimal formats have one-to-many maps between numeric values and their encodings. By way of illustration, three hundred could be represented with bits whose direct meaning is 3•102 or bits whose direct meaning is 300•100. Again, since these represent the same mathematical value, it would be permissible under the C++ standard to store one in the left operand of an assignment when the right operand is the other.
IEEE-754 includes many non-numeric entities called NaNs (for Not a Number), and a C++ implementation might store a NaN different from the right operand. This could include either replacing any NaN with a “canonical” NaN for the implementation or, upon assignment of a signaling Nan, indicating the signal in some way and then converting the signaling NaN to a quiet NaN and storing that.
Non-IEEE-754 formats may have similar issues.
Regarding the latter question, can a == b be false after a = b, where both a and b have type double, the answer is no. The C++ standard does require that an assignment replace the value of the left operand with the value of the right operand. So, after a = b, a must have the value of b, and therefore they are equal.
Note that the C++ standard does not impose any restrictions on the accuracy of floating-point operations (although I see this only stated in non-normative notes). So, theoretically, one might interpret assignment or comparison of floating-point values to be floating-point operations and say that they do not need to be accuracy, so the assignment could change the value or the comparison could return an inaccurate result. I do not believe this is a reasonable interpretation of the standard; the lack of restrictions on floating-point accuracy is intended to allow latitude in expression evaluation and library routines, not simple assignment or comparison.
One should note the above applies specifically to a double object that is assigned from a simple double operand. This should not lull readers into complacency. Several similar but different situations can result in failure of what might seem intuitive mathematically, such as:
After float x = 3.4;, the expression x == 3.4 will generally evaluate as false, since 3.4 is a double and has to be converted to a float for the assignment. That conversion reduces precision and alters the value.
After double x = 3.4 + 1.2;, the expression x == 3.4 + 1.2 is permitted by the C++ standard to evaluate to false. This is because the standard permits floating-point expressions to be evaluated with more precision than the nominal type requires. Thus, 3.4 + 1.2 might be evaluated with the precision of long double. When the result is assigned to x, the standard requires that the excess precision be “discarded,” so the value is converted to a double. As with the float example above, this conversion may change the value. Then the comparison x == 3.4 + 1.2 may compare a double value in x to what is essentially a long double value produced by 3.4 + 1.2.

Can 'inf' be assigned to a variable like regular numeric values in c++

When I wrote the following code, instead of causing runtime error, it outputs 'inf'. Now, is there any way to assign this value ('inf') to a variable, like regular numeric values? How to check if a division yields 'inf'?
#include<iostream>
int main(){
double a = 1, b = 0;
std::cout << a / b << endl;
return 0;
}
C++ does not require implementations to support infinity or division by zero. Many implementations will, as many implementations use IEEE 754 formats even if they do not fully support IEEE 754 semantics.
When you want to use infinity as a value (that is, you want to refer to infinity in source code), you should not generate it by dividing by zero. Instead, include <limits> and use std::numeric_limits<T>::infinity() with T specified as double.
Returns the special value "positive infinity", as represented by the floating-point type T. Only meaningful if std::numeric_limits< T >::has_infinity== true.
(You may also see code that includes <cmath> and uses INFINITY, which are inherited from C.)
When you want to check if a number is finite, include <cmath> and use std::isfinite. Note that computations with infinite values tend to ultimately produce NaNs, and std::isfinite(x) is generally more convenient than !std::isinf(x) && !std::isnan(x).
A final warning in case you are using unsafe compiler flags: In case you use, e.g., GCC's -ffinite-math-only (included in -ffast-math) then std::isfinite does not work.
It appears to be I can:
#include<iostream>
int main(){
double a = 1, b = 0, c = 1/0.0;
std::cout << a / b << endl;
if (a / b == c) std::cout << "Yes you can.\n";
return 0;
}

How to set returned value of log10(0)?

Code:
#include <iostream>
#include <math.h>
using namespace std;
int main ()
{
double result = log10(0.0);
cout << result;
}
When I execute log10(0) in C++, It prints to me -inf.
Is it fixed for every library/compiler I'll use?
Or could it change in different platforms?
How would you manage the pole error keeping double?
According to cplusplus, it depends on the library what you get for log10(0). However, in general the value of log10(0) is not defined (can be -inf if you like, but it is not a real number). Usually, you should prevent such undefined results (not undefined in the C++ sense of Undefined Behaviour, but in a mathematical sense) before they happen. E.g.
double x;
x = foo();
if ( x <= 0 ) {
/* handle this case extra */
else {
y = log10(x);
}
What value you use in the case of log10(0) depends very much on your application. However, I think it is easier to check for 0 before doing the calculation instead of relying on log10(0) returning some particular value (as it might be -inf or something completely different).
The behavior is very clear-cut for log10 for floating point implementations that are IEC 60559 compliant:
If the argument is ±0, -∞ is returned and FE_DIVBYZERO is raised.
If the argument is 1, +0 is returned
If the argument is negative, NaN is returned and FE_INVALID is raised.
If the argument is +∞, +∞ is returned
If the argument is NaN, NaN is returned
This list would allow you to conditionally handle each case for compliant implementations. But honestly, we know that only the range (+0, +∞) is supported, so whether your implementation is compliant or not you could simply guard your log10 with an if-block.
A great way to write this if-block is with isnormal if you don't want to allow denormals or isfinite if you do want to support denormals. For example, given a floating point variable foo:
if(isfinite(foo) && foo > 0) {
cout << log10(foo) << endl;
} else {
cout << "foo is invalid\n";
}
But the answer to your question is no -∞ will not always be returned. But C++ does guarantee a return: Given log10(foo):
If foo is a float the return will always be -HUGE_VALF
If foo is a double the return will always be -HUGE_VAL
If foo is a long double the return will always be -HUGE_VALL
On implementations that support floating-point infinities, these macros always expand to the positive infinities of float, double, and long double, respectively [source]
Whether your implementation supports infinity or whether these values expand to the maximum floating point value, the right way to handle this is still probably isnormal/isfinite but you could also test the return of log10:
const auto result = log10(foo);
if(is_same_v<decltype(foo), float> && result == -HUGE_VALF ||
is_same_v<decltype(foo), double> && result == -HUGE_VAL ||
is_same_v<decltype(foo), long double> && result = -HUGE_VALL) {
cout << "foo is invalid\n";
} else {
cout << result << endl;
}
Well c++ ref gives clear answer: cpp ref.
If the argument is ±0, -∞ is returned and FE_DIVBYZERO is raised.
So yes, log10(0) will give you -inf, doesn't matter what library/compiler you use (as long as it's in line with spec).
In math there is no option to calculate log(0)

What is result of comparison of double and NaN?

I have the following program:
#include <iostream>
#include <cmath>
int main() {
double a = 1;
double b = nan("");
std::cout << (a > b) << std::endl;
std::cout << (b > a) << std::endl;
return 0;
}
Output:
0
0
In general from the meaning of nan - not a number it is clear that any operation with nan is essentially pointless. From IEEE-754 that I found in internet I found what if in FPU at least one of operands is nan the result is also nan, but I found nothing about comparison between normal value and nan as in example above.
What does standard say about it?
What does standard say about it?
The C++ standard does not say how operations on NaNs behave. It is left unspecified. So, as far as C++ is concerned, any result is possible and allowed.
ANSI/IEEE Std 754–1985 says:
5.7. Comparison
... Every NaN shall compare unordered with everything, including itself. ...
What unordered means exactly is shown in the Table 4 in the same section. But in short, this means that the comparison shall return false, if any of the operands is NaN, except != shall return true.
The 0 you're seeing means false in this case as that's what the stream shows for false by default. If you want to see it as true or false use std::boolalpha:
std::cout << std::boolalpha << (a > b) << std::endl;
Whey comparing floating point values where one of the values is nan then x<y, x>y, x<=y, x>=y, and x==y will all evaluate to false, whereas x!=y will always be true. Andrew Koenig has a good article on this on the Dr Dobbs website.
When you think about it the result cannot be nan since comparison operators need to return a boolean which can only have 2 states.
0 here means false.
Nan is not equal or comparable to any value so the result of operation is false(0).
Well, on top of #user2079303 pretty good answer, there are two NaNs: quiet NaN and signaling NaN. You could check std::numeric_limits<T>::has_signaling_NaN on your platform is signaling NaN is available. If it is true and value contains std::numeric_limits<T>::signaling_NaN, then
When a signaling NaN is used as an argument to an arithmetic expression, the appropriate floating-point exception may be raised and the NaN is "quieted", that is, the expression returns a quiet NaN.
To really get FP exception you might want to set FPU control word (for x87 unit) or MXCSR register (for SSE2+ unit). This is true for x86/x64 platform, check your platform docs for similar functionality

Is there a double value which will remain itself despite any computation applied to it?

On the Windows XP..7 platforms, for x86 instruction sets, using standard C++ or a Microsoft compiler, is there a value I can assign a double which, when other computations are applied to it, will always result in that same value?
e.g.
const double kMagicValue = ???;
double x = kMagicValue;
cout << x * 9.1; // still outputs kMagicValue
As I understand it, there is a floating point error condition that once trigged, the remainder of all floating point computations will result in NAN or something similar...
I ask because I have a series of functions that try to compute a double for a given input, and for some inputs, "no answer (NAN)" is a good output (conceptually).
And I want to be able to be lazy, and string together computations that should, if any part results in NAN, result as a whole in NAN (i.e. kMagicValue).
Quiet NaN should do just fine. You can get it from std::numeric_limits<double>::quiet_NaN() by including the <limits> header. There's also a signaling NaN, but using it will usually result in an exception.
Remember however, that you can't simple use mydouble == qNaN, since NaN compares equal to nothing, not even itself. You have to use that property of NaN to test it: bool isNaN = mydouble != mydouble;.
Any floating point operation involving NaN results in NaN again (to my knowledge). Moreover, NaN compares unequal to itself, and it is unique among IEEE754 floats with this property. So, to test for it:
bool is_nan(double x) { return x != x; }
If you have C++11 support, you can use std::isnan(x) != 0 or std::fpclassify(x) == std::FP_NAN from <cmath> instead [thanks #James Brock].
To make it:
double make_nan() {
assert(std::numeric_limits<double>::has_quiet_NaN);
return std::numeric_limits<double>::quiet_NaN();
}
You shouldn't rely on NaN to do the job. It will always compare false to any value, including itself, and you have to make sure that the platform respects IEEE754 semantics to a certain extent (this includes having a NaN in the first place).
See horror stories there: Negative NaN is not a NaN?
If you really want this approach, and you are confident enough about IEEE754 support, be sure to compile with /fp:precise (since you use MSVC) so that the compiler doesn't optimize away stuff like 0 * NaN. Be aware that this might impact performance.
To get a NaN,
std::numeric_limits<double>::quiet_NaN()
To test for NaN
inline bool is_NaN(double x) { return !(x == x); }
But this approach is probably more trouble than it is worth. I'd rather use exceptions for control flow here.
The right thing to use is boost::optional<double>, but it can be a little verbose at some places
[Also, the Haskell language has first-class support for these kind of control flow, if C++ is not a must-go option, Maybe you can give it a try.]
Actually there is a special floating point value named Not-A-Number (NaN). Any expression with NaN involved will return NaN.
#include <limits>
numeric_limits<double>::quiet_NaN()
Infinity not always remains the same. For example it become NaN if you try to divide on Infinity.