472,371 Members | 1,585 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,371 software developers and data experts.

pow() problem

Can anyone tell me why pow(-8.0, 1.0 / 3.0) (cubic root of -8) returns
nan (in linux) and negative infinity or something (in devcpp in
windows), instead of -2?

The problem seems to be that pow can't handle cubic root of negative
number, I mean, a calculator could do it or am I using the wrong
function here. My current solution is a hack which detects negative
input and handle it differently.

I suspect it is something to do with the fact the power is represented
as a floating point value.
Nov 14 '05 #1
13 5607


Shaobo Hou wrote:
Can anyone tell me why pow(-8.0, 1.0 / 3.0) (cubic root of -8) returns
nan (in linux) and negative infinity or something (in devcpp in
windows), instead of -2?

The problem seems to be that pow can't handle cubic root of negative
number, I mean, a calculator could do it or am I using the wrong
function here. My current solution is a hack which detects negative
input and handle it differently.

I suspect it is something to do with the fact the power is represented
as a floating point value.


In a way, yes: the second argument to pow() is not
exactly one-third, but a nearby value. You aren't actually
calculating "the cube root of -8," but "-8 raised to a
rational exponent close to one-third." That exponent value
is a fraction of the form U/V where U,V are integers and V is
almost certainly a large power of two. Mathematically
speaking,

pow(-8, U/V)
== pow(pow(-8, 1/V), U)
== pow(sqrt(sqrt(...(-8)...)), U)

(since V is a power of two), and this can't be evaluated
in real arithmetic.

Some suggestions:

- The latest "C99" Standard defines a cbrt() function.
Even if you don't have access to a full-blown C99
implementation, you may find that cbrt() is present.

- If cbrt() isn't available, try something like
(x >= 0.0) ? pow(x, 1.0/3.0) : -pow(-x, 1.0/3.0)

- If your system has copysign(), try writing the above as
copysign(pow(fabs(x), 1.0/3.0), x)

--
Er*********@sun.com

Nov 14 '05 #2
On Tue, 22 Feb 2005 15:12:57 +0000, Shaobo Hou said to the parser:
Can anyone tell me why pow(-8.0, 1.0 / 3.0) (cubic root of -8) returns nan
(in linux) and negative infinity or something (in devcpp in windows),
instead of -2?

The problem seems to be that pow can't handle cubic root of negative
number, I mean, a calculator could do it or am I using the wrong function
here. My current solution is a hack which detects negative input and
handle it differently.

I suspect it is something to do with the fact the power is represented as
a floating point value.


It has more to do with the -8...

The below demonstrates one method for handling this, which may be what you
did already, when you mention your current solution detects negative input
and handles it differently.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(void)
{
float num = -8;
float result;

if (num >= 0)
result = pow(num, 1.0/3.0);
else
result = -pow(-num, 1.0/3.0);

printf("%f\n", result);

return EXIT_SUCCESS;
}
Nov 14 '05 #3
In article <cv*********@wapping.cs.man.ac.uk>,
Shaobo Hou <ho***@cs.man.ac.uk> wrote:
:Can anyone tell me why pow(-8.0, 1.0 / 3.0) (cubic root of -8) returns
:nan (in linux) and negative infinity or something (in devcpp in
:windows), instead of -2?

:I suspect it is something to do with the fact the power is represented
:as a floating point value.

Plausibly. 1/3 is not exactly representable in binary, so whether
1/3 comes out "odd" or "even" (which would allow you to square the
x first) would be dependant on the precision you are working with.
--
Those were borogoves and the momerathsoutgrabe completely mimsy.
Nov 14 '05 #4
Eric Sosman wrote:
- If cbrt() isn't available, try something like
(x >= 0.0) ? pow(x, 1.0/3.0) : -pow(-x, 1.0/3.0)


This is essentially what I did. thanks
Nov 14 '05 #5
Shaobo Hou wrote:
Can anyone tell me why pow(-8.0, 1.0 / 3.0) (cubic root of -8) returns
nan (in linux) and negative infinity or something (in devcpp in
windows), instead of -2?

From C99 section 7.12.7.4, the pow functions:

``A domain error occurs if x is finite and negative and y is finite and
not an integer value.''

pow() is a generic power function and in general a negative number
raised to a non-integral power will result in a complex number. It would
need to special case x**(1/(2**n)) and x**(1/(2**n+1)) which would be
tricky.
The problem seems to be that pow can't handle cubic root of negative
number, I mean, a calculator could do it or am I using the wrong
function here. My current solution is a hack which detects negative
input and handle it differently.


C99 has cbrt()

--
Kyle A. York
Sr. Subordinate Grunt
Nov 14 '05 #6

Walter Roberson wrote:
In article <cv*********@wapping.cs.man.ac.uk>,
Shaobo Hou <ho***@cs.man.ac.uk> wrote:
:Can anyone tell me why pow(-8.0, 1.0 / 3.0) (cubic root of -8) returns :nan (in linux) and negative infinity or something (in devcpp in
:windows), instead of -2?

:I suspect it is something to do with the fact the power is represented :as a floating point value.

Plausibly. 1/3 is not exactly representable in binary, so whether
1/3 comes out "odd" or "even" (which would allow you to square the
x first) would be dependant on the precision you are working with.


That's nonsense. pow is normally implemented as

pow(a, b) = exp(ln(a) * b)

It may or may not abs() "a" which is where the problems will occur
because the ln of -a is not defined.

Tom

Nov 14 '05 #7
On Tue, 22 Feb 2005 15:12:57 +0000, Shaobo Hou
<ho***@cs.man.ac.uk> wrote:
Can anyone tell me why pow(-8.0, 1.0 / 3.0) (cubic root of -8) returns
nan (in linux) and negative infinity or something (in devcpp in
windows), instead of -2?

The problem seems to be that pow can't handle cubic root of negative
number, I mean, a calculator could do it or am I using the wrong
function here. My current solution is a hack which detects negative
input and handle it differently.

I suspect it is something to do with the fact the power is represented
as a floating point value.


The parameters to pow(x, y) are always floating point. However:

7.12.7.4 The pow functions

2 The pow functions compute x raised to the power y. A domain error
occurs if x is negative and y is finite and not an integer value.

Among other things, 1.0 / 3.0 is not 1/3, it's an approximation, so the
function can't tell that it has a real answer at all (only fractional
powers with an odd integral divisor have real roots, others have complex
roots.

C99 has the function cbrt() which calculates a cube root specifically
(as, I suspect, does your calculator). However, there are few
conforming C99 libraries yet (after all, that specification has only
been out for 6 years!).

In general it is better to give an error if the programmer tries to do
something which has an unrepresentable result.

I would implement my own cube root function, either "from scratch"
(using Newton/Raphson or a better algorithm) or as:

double myCubeRoot(double x)
{
return (x >= 0 ? pow(x, 1.0/3.0) : -pow(-x, 1.0/3.0));
}

(or as a macro).

Note that since pow() uses exp(log(x)*y) (or a faster equivalent) it
will in general be slower than a special-purpose cube root function, as
well as being less accurate (see above about binary approcimation to
fractions).

Chris C
Nov 14 '05 #8


Tom St Denis wrote:
[...]
That's nonsense. pow is normally implemented as

pow(a, b) = exp(ln(a) * b)


(Slight topic drift): For suitable values of "normally,"
with implications of "quick and dirty." This is not a very
accurate implementation of pow(), and I wouldn't expect to
find it in a high-quality math library. Reference: "The
Standard C Library" by P.J. Plauger gives a brief but quite
understandable explanation of the problems and exhibits an
implementation that mitigates them.

--
Er*********@sun.com

Nov 14 '05 #9
AC

"Shaobo Hou" <ho***@cs.man.ac.uk> wrote in message
news:cv*********@wapping.cs.man.ac.uk...
Can anyone tell me why pow(-8.0, 1.0 / 3.0) (cubic root of -8) returns nan
(in linux) and negative infinity or something (in devcpp in windows),
instead of -2?

The problem seems to be that pow can't handle cubic root of negative
number, I mean, a calculator could do it or am I using the wrong function
here. My current solution is a hack which detects negative input and
handle it differently.

I suspect it is something to do with the fact the power is represented as
a floating point value.


The first argument has to be positive.

7.12.7.4 The pow functions

Synopsis

1 #include <math.h>

double pow(double x, double y);

float powf(float x, float y);

long double powl(long double x, long double y);

Description

The pow functions compute x raised to the power y. *A domain error occurs
if x is finite and negative* and y is finite and not an integer value. A
domain error may occur if x is zero and y is less than or equal to zero. A
range error may occur.
Nov 14 '05 #10
On Tue, 22 Feb 2005 13:38:10 -0500, AC
<te**@test.test> wrote:
"Shaobo Hou" <ho***@cs.man.ac.uk> wrote in message
news:cv*********@wapping.cs.man.ac.uk...
Can anyone tell me why pow(-8.0, 1.0 / 3.0) (cubic root of -8) returns nan
(in linux) and negative infinity or something (in devcpp in windows),
instead of -2?

The problem seems to be that pow can't handle cubic root of negative
number, I mean, a calculator could do it or am I using the wrong function
here. My current solution is a hack which detects negative input and
handle it differently.

I suspect it is something to do with the fact the power is represented as
a floating point value.
The first argument has to be positive.


Or the second argument has to be finite and an integer value. Read
what you quoted:
7.12.7.4 The pow functions

Synopsis

1 #include <math.h>

double pow(double x, double y);

float powf(float x, float y);

long double powl(long double x, long double y);

Description

The pow functions compute x raised to the power y. *A domain error occurs
if x is finite and negative* and y is finite and not an integer value.

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There's an 'and' clause in there, pow(-8.0, 3) is valid, for instance
(the 3 is promoted to a double as long as the prototype is in scope).

Chris C
Nov 14 '05 #11
AC

"Chris Croughton" <ch***@keristor.net> wrote in message
news:sl******************@ccserver.keris.net...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There's an 'and' clause in there, pow(-8.0, 3) is valid, for instance
(the 3 is promoted to a double as long as the prototype is in scope).

Chris C


You are right, I should have mentioned that too.
Nov 14 '05 #12

Eric Sosman wrote:
Tom St Denis wrote:
[...]
That's nonsense. pow is normally implemented as

pow(a, b) = exp(ln(a) * b)


(Slight topic drift): For suitable values of "normally,"
with implications of "quick and dirty." This is not a very
accurate implementation of pow(), and I wouldn't expect to
find it in a high-quality math library. Reference: "The
Standard C Library" by P.J. Plauger gives a brief but quite
understandable explanation of the problems and exhibits an
implementation that mitigates them.


pow(a, b) = exp(ln(a) * b)

is EXACTLY correct.

.... however as implemented [and executed] it may not be ideal. The
"crux" of what the pow function does is probably along the lines of the
equivalence since you can easily find exp and ln from two convergent
series.

Tom

Nov 14 '05 #13


Tom St Denis wrote:
Eric Sosman wrote:
Tom St Denis wrote:
[...]
That's nonsense. pow is normally implemented as

pow(a, b) = exp(ln(a) * b)
(Slight topic drift): For suitable values of "normally,"
with implications of "quick and dirty." This is not a very
accurate implementation of pow(), and I wouldn't expect to
find it in a high-quality math library. Reference: "The
Standard C Library" by P.J. Plauger gives a brief but quite
understandable explanation of the problems and exhibits an
implementation that mitigates them.

pow(a, b) = exp(ln(a) * b)

is EXACTLY correct.


My apologies; I'd assumed that because you said
"implemented as" you intended this as a C expression
(with `log' misspelled) rather than as a mathematical
expression.
... however as implemented [and executed] it may not be ideal.


This was the point of my post: Interpreted as a C
expression, exp(log(a) * b) is a poor way to implement
pow(a,b).

--
Er*********@sun.com

Nov 14 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: berthelot samuel | last post by:
Hi, I'm trying to do this : double term2 = 0.0; term2 = pow (0.1, 2.0); the only thing I get in term2 is 1. it should be 0.01. Why is that ? I don't get it... pow() is supposed to work with...
52
by: Michel Rouzic | last post by:
I obtain an unwanted behavior from the pow() function : when performing pow(2, 0.5), i obtain 1.414214 when performing pow(2, 1/2), i obtain 1.000000 when performing a=0.5; pow(2, a), i obtain...
11
by: Russ | last post by:
I have a couple of questions for the number crunchers out there: Does "pow(x,2)" simply square x, or does it first compute logarithms (as would be necessary if the exponent were not an integer)?...
42
by: John Smith | last post by:
In a C program I need to do exponentiation where the base is negative and the exponent is a fraction. In standard C this would be something like t = pow(-11.5, .333), but with this combination of...
2
by: merrittr | last post by:
I have a small program to read data from some data files , in it I use string types to build the data file name but when I try to compile it I get: (see code below error) ...
18
by: Peng Yu | last post by:
Hi, I'm wondering if there is any general guideline on when to using something like std::pow(x, n) rather than x * x * x * ... * x (n x's). Thanks, Peng
2
by: Kemmylinns12 | last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and efficiency. While initially associated with cryptocurrencies...
0
by: Naresh1 | last post by:
What is WebLogic Admin Training? WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge required to effectively administer and manage Oracle...
0
hi
by: WisdomUfot | last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific technical details, Gmail likely implements measures...
1
by: Matthew3360 | last post by:
Hi, I have been trying to connect to a local host using php curl. But I am finding it hard to do this. I am doing the curl get request from my web server and have made sure to enable curl. I get a...
0
by: Rahul1995seven | last post by:
Introduction: In the realm of programming languages, Python has emerged as a powerhouse. With its simplicity, versatility, and robustness, Python has gained popularity among beginners and experts...
2
by: Ricardo de Mila | last post by:
Dear people, good afternoon... I have a form in msAccess with lots of controls and a specific routine must be triggered if the mouse_down event happens in any control. Than I need to discover what...
1
by: Johno34 | last post by:
I have this click event on my form. It speaks to a Datasheet Subform Private Sub Command260_Click() Dim r As DAO.Recordset Set r = Form_frmABCD.Form.RecordsetClone r.MoveFirst Do If...
1
by: ezappsrUS | last post by:
Hi, I wonder if someone knows where I am going wrong below. I have a continuous form and two labels where only one would be visible depending on the checkbox being checked or not. Below is the...
0
by: jack2019x | last post by:
hello, Is there code or static lib for hook swapchain present? I wanna hook dxgi swapchain present for dx11 and dx9.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.