Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Math.Pow() is broken

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!?

like image 531
cowlinator Avatar asked Jan 16 '13 20:01

cowlinator


3 Answers

Seems to be exactly as specified; from the Math.Pow() remarks section on Pow(x,y);

Parameters
x < 0 but not NegativeInfinity; y is not an integer, NegativeInfinity, or PositiveInfinity.

Result
NaN

like image 191
Joachim Isaksson Avatar answered Nov 14 '22 15:11

Joachim Isaksson


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 the 0.14285714285714285 power of -128.0, and there is no real number with that property, so the result is correctly NaN. For all odd n != 1, 1.0/(double)n is not exactly representable, so you can't compute the nth root of x by using pow(x, 1.0/(double)n). Therefore pow(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.

like image 20
Stephen Canon Avatar answered Nov 14 '22 15:11

Stephen Canon


The problem here is the mathematical definition of "seventh root" is a multivalued function. While it is true that

(-2)7 = -128

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 the pow function. When the principal value of the result would be a complex number, it returns NaN.

like image 3
Greg Hewgill Avatar answered Nov 14 '22 15:11

Greg Hewgill