Solved

pow (-27.0, -1.0 / 3.0) undefined?

Posted on 2002-03-28
10
1,007 Views
Last Modified: 2008-02-01
Running Windows XP Home, VC 6 SP5

Why do both of these code fragments display "-1.#IND00, 33"?

  errno = 0;
  double c = 1.0 / pow (-27.0, 1.0 / 3.0);
  printf ("%f, %d\r\n", c, errno);

  errno = 0;
  double d = pow (-27.0, -1.0 / 3.0);
  printf ("%f, %d\r\n", d, errno);

If errno == 33, that means "EDOM" or "Math argument." (according to MSDN)

Is this the way pow is supposed to work?  It seems to me that 1 / ((-27)^(1/3)) = -1/3.  What am I missing?
0
Comment
Question by:thresher_shark
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
10 Comments
 
LVL 4

Expert Comment

by:mblat
ID: 6904163
pow (-27.0, -1.0 / 3.0) is actually undefined.

MSDN says that pow return INF if y (second parameter) is less than 0.
0
 
LVL 6

Author Comment

by:thresher_shark
ID: 6904210
Thank you for your prompt response.  However, according to:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_CRT_pow.asp

pow returns INF if the second parameter is less than 0 AND the first parameter is equal to 0:  "[if] x = 0.0 and y < 0 [then result is] INF"

Furthermore, if the following code is executed:

  errno = 0;
  double a = pow (4.0, -1.0 / 2.0);
  printf ("%f, %d\r\n", a, errno);

you get the expected value of .5..., even though the second parameter is less than 0.
0
 
LVL 22

Expert Comment

by:cookre
ID: 6904259
I would suggest their documentation is defective.  Their description for java's Math.pow adds:

An exception also will occur if (a <= 0.0) and b is not equal to a whole number.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 22

Expert Comment

by:cookre
ID: 6904266
After all, consider pow(-16.0,-.25)
0
 
LVL 1

Expert Comment

by:ilikenine
ID: 6905354
use powf() instead of pow()
0
 
LVL 6

Author Comment

by:thresher_shark
ID: 6905595
Considering that the function clearly doesn't do what it claims to (according to the documentation), it seems that the documentation is indeed defective.  So, how does one perform calculations like the one described in the original question in C++?  Surely there is a way... every scientific calculator has this functionality, as does the lame calculator that comes with Windows.  How do they do it?  Am I going to have to write my own function that deals with situations like these?

I guess what I am looking for is some authoritative website that says "yes, this is the way ANSI C defines pow (that is, pow need not handle these kinds of calculations)" or "no, ANSI C says pow should work in this case and it should return -.33333".  If pow should work in this case, but isn't, then it's Microsoft's problem and I will have to come up with a workaround.  If pow isn't supposed to work in this case, then at least it's not Microsoft's problem, but I'll still have to come up with a workaround.

>> Their description for java's Math.pow adds:
>> An exception also will occur if (a <= 0.0) and b is not equal to a whole number.

Since this is C++, I don't think the documentation for the Java equivalent is very relavent :)

ilikenine, powf produces the same exact results.
0
 
LVL 6

Author Comment

by:thresher_shark
ID: 6905628
Shoot, it may be that pow is defined as e^(y * ln (x)) in which case it would fail in these situations.  Do you suppose that's what the problem is?
0
 
LVL 22

Expert Comment

by:cookre
ID: 6906079
Just think about what an exponent less than 1 is - it's asking for the root.  So let's look at the easy to understand cases in which the fraction can be expressed as 1/k, i.e., the kth root.  So, z=pow(x,1/k) is that z such that z**k=x

Now, in the one case you presented, pow(-27,1/3), we can easily say -3, since -3**3 is -27, just as we could for any kth odd root of any negative integer that's the kth power of some other integer.

But how would we express pow(-16,1/4) if not undefined without introducing some new data type akin to imaginary?

As to the comparison with Java, I would argue that, in this case, it is legitimate.  This question does not deal with the implementation of iterations, conditionals, or other syntactic features that are naturally specific to any given language.  Rather, this case deals with the definition of a well understood mathematical function, the invalid arguments of which I have found to be fully documented everywhere else I looked.

In any case, this, alas, is far from the only case of incomplete documentation from MS.

As to its' implementation, I don't know how MS does it in their current library, but it has been quite common over the decades to simplify library implementations by internally implementing as many functions as possible as some combination of calls to other functions. Presuming negligable performance degradation (i.e., speed, precision, or accuracy), this improves maintainability.


Historical side note of questionable interest: Some flavors of FORTRAN implemented IMAGINARY 30 years ago.
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 50 total points
ID: 6906226
I traced into the library code for the _pow() fn and it implements by using the FPU opcode FYL2X.  Looking that up in the intel dox indicates:
--==--=-=-=-=-=-=-=-=-=-=-=-=-=
Computes (ST(1) &#8727; log2 (ST(0))), stores the result in resister ST(1), and pops the FPU register stack. The source operand in ST(0) must be a non-zero positive number.
--==--=-=-=-=-=-=-=-=-=-=-=-=-=
In the Microsoft library implementatiion, if pushes the 1/3 onto the stack, then pushed the -27 onto the stack, then it checks the high bit of -27 and thereby determines that it is a negative number.  So it never actually executes the FYL2X opcode -- it jumps right into the error handler.

Although Intel is not the final arbitrator of what is valid and what is not valid, I think that there may have been at least one lowly Intel technician who went to the trouble of looking up the EEE spec before commiting the 80x87 FPU to silicon.

Finally, some people might blame Microsoft for implementing the pow() fn by following the Intel documentation, but you should not find me to be numbered among them.

-- Dan
0
 
LVL 6

Author Comment

by:thresher_shark
ID: 6906338
Thank you cookre and Dan.  You have both provided very useful information.  cookre, you may find another question in this topic area with the subject "For cookre".  Please post there and you will also get 50 points.
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

627 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question