I understood why Math.pow(a, b)
is NaN when a
is a negative number and b
is a non-integer in JavaScript. Same is happening in other programming languages.
But, what about C++?
While in JavaScript Math.pow(-4, -2.1)
returns NaN
, in C++ pow (-4, -2.1)
returns -nan
. Why?
Example:
#include <iostream>
#include <math.h>
using namespace std;
int main () {
cout << "(4) ^ (2.1) = " << pow (4, -2.1) << endl; // 0.0544094
cout << "(-4) ^ (-2.1) = " << pow (-4, -2.1) << endl; // -nan
cout << "(-4) ^ (2.1) = " << pow (-4, 2.1) << endl; // -nan
return 0;
}
Output:
(4) ^ (2.1) = 0.0544094
(-4) ^ (-2.1) = -nan
(-4) ^ (2.1) = -nan
I piled the code using g++
.
$ g++ --version
g++ (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Tried that to pile it using online tools but same result is shown:
- (C++11)
- (C++ 4.8.1)
- .php
I understood why Math.pow(a, b)
is NaN when a
is a negative number and b
is a non-integer in JavaScript. Same is happening in other programming languages.
But, what about C++?
While in JavaScript Math.pow(-4, -2.1)
returns NaN
, in C++ pow (-4, -2.1)
returns -nan
. Why?
Example:
#include <iostream>
#include <math.h>
using namespace std;
int main () {
cout << "(4) ^ (2.1) = " << pow (4, -2.1) << endl; // 0.0544094
cout << "(-4) ^ (-2.1) = " << pow (-4, -2.1) << endl; // -nan
cout << "(-4) ^ (2.1) = " << pow (-4, 2.1) << endl; // -nan
return 0;
}
Output:
(4) ^ (2.1) = 0.0544094
(-4) ^ (-2.1) = -nan
(-4) ^ (2.1) = -nan
I piled the code using g++
.
$ g++ --version
g++ (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Tried that to pile it using online tools but same result is shown:
- http://ideone./4xqNU7 (C++11)
- http://ideone./4xqNU7 (C++ 4.8.1)
- http://www.pileonline./pile_cpp0x_online.php
- 2 stackoverflow./questions/8817164/signed-nan-values – NPE Commented Dec 8, 2013 at 11:40
- 2 stackoverflow./questions/8781072/sign-check-for-nan-value – NPE Commented Dec 8, 2013 at 11:40
- 2 stackoverflow./questions/3772835/… – NPE Commented Dec 8, 2013 at 11:41
-
Btw, the behaviour you observe is not required in C++, it's an implementation detail. All that's required is that a NaN is returned. How many NaNs an implementation has, and what they are, is up to the specific implementation.
-nan
is a permitted result of printing a NaN. You might have to look at the source forpow
in glibc to figure out whether it returns the negative NaN intentionally as a special case. – Steve Jessop Commented Dec 8, 2013 at 11:54
2 Answers
Reset to default 5The only relevant quote I can find is from n1570.
An implementation may give zero and values that are not floating-point numbers (such as infinities and NaNs) a sign or may leave them unsigned. Wherever such values are unsigned, any requirement in this International Standard to retrieve the sign shall produce an unspecified sign, and any requirement to set the sign shall be ignored.
If x is finite negative and y is finite but not an integer value, it causes a domain error. If both x and y are zero, it may also cause a domain error. If x is zero and y is negative, it may cause a domain error or a pole error (or none, depending on the library implementation). The function may also cause a range error if the result is too great or too small to be represented by a value of the return type.
In your case
x = -4 and y = -2.1, so x is finite negative and y is finite but not an integer value. Now read the quoted text again ;)
Taken from here.
EDIT: The domain of a function is the set where the function is defined. pow expects the second parameter to be integer in case the first parameter is integer. The library clearly states this is the case.
Let me state it this way:
-4^-2.1 = (-1)^-2.1 * 4^-2.1
What should be the value of
(-1)^2.1
?
sqrt(-1)
is undefined for real numbers
sqrt(-1) = i
for plex numbers. Clearly, the return value of pow is a real number. Now it is impossible to calculate
-1^-0.1
on the set of real numbers, so it is a natural mathematical consequence that it is a NaN (not a number), because it is not a real number in this case. To understand more details you have to study a lot of number theory.