And no, this does not (to my understanding) involve integer division or floating-point rounding issues.
My exact code is:
static void Main(string[] args)
{
double power = (double)1.0 / (double)7.0;
double expBase = -128.0;
System.Console.WriteLine("sanity check: expected: -128 ^ 0.142857142857143 = -2. actual: " + expBase + " ^ " + power + " = " + Math.Pow(expBase, power));
System.Console.ReadLine();
}
The output is:
sanity check: expected: -128 ^ 0.142857142857143 = -2. actual: -128 ^ 0.14285
7142857143 = NaN
The Target Framework for this code is (according to solution properties) .NET Framework 4.0 Client Profile.
Strangely I haven't found any mention of this anywhere on the Web. Am I taking crazy pills here!?
The problem here is the mathematical definition of "seventh root" is a multivalued function. While it is true that
this does not mean that -2 is the only answer to (-128)1/7. In the complex plane, the seventh-root function is multivalued and has many possible answers (just as the square root of 4 can be considered to be either +2 or -2, but +2 is the usual answer).
In order to simplify the mathematical handling of such expressions, the principal value is chosen by convention for the function in question so that the function becomes single-valued. In the case of seventh-root, the principal value is that given by Wolfram Alpha for (-128)1/7.
The
Math.Pow()
function in C# attempts to return the principal value for thepow
function. When the principal value of the result would be a complex number, it returnsNaN
.Seems to be exactly as specified; from the Math.Pow() remarks section on
Pow(x,y)
;I fixed Math.Pow().
It now has a larger accepted domain (i.e. for Parameters: x < 0 but not NegativeInfinity; y is a fraction with a numerator of 1 and an odd denominator), and returns a real number result for the new domain area.
In other words, (-128)^(1/7) returns -2.
Note: due to double-float precision limitations, it will work for most, but not all, fractional exponents.
Below is the code for the wrapper for Math.Pow() I wrote.
For 1.0/3 != 1/3 ,I use Rational that can Accurately represent 1/3 in Microsoft.SolverFoundation.Common .See:https://msdn.microsoft.com/en-us/library/microsoft.solverfoundation.common.rational%28v=vs.93%29.aspx?f=255&MSPPError=-2147217396
And I can catch the odd root link 1/3 for I can get the Denominator.
If I get a root is ax that I use the code get the Numerator and Denominator.
Rational can make the 2/6=1/3.
But the Rational.Pow cant calculate powerBase isnt positive.
I find the powerBase isnt positive and the Denominator is even and Numerator is odd.
If the Denominator is odd ,I use
x = x * -1
If the Numerator is even ,the pow of Numerator make powerBase is positive.
Like pow(x,2/3), if x isnt positive ,it will be positive when use pow(x,2)
The code you can use
Joachim's answer explains that pow is behaving according to its specification.
Why is pow( ) specified that way? Because
1.0/7.0
is not equal to 1/7. You are asking for the0.14285714285714285
power of-128.0
, and there is no real number with that property, so the result is correctly NaN. For all oddn != 1
,1.0/(double)n
is not exactly representable, so you can't compute the nth root of x by usingpow(x, 1.0/(double)n)
. Thereforepow(x, y)
is specified to return NaN for negative x and non-integer y -- there is no appropriate real result for any of those cases.A fractional power of a negative real number is a complex number (see Math Forum for a detailed explanation).