I am using math.h with GCC and GSL. I was wondering how to get this to evaluate?

I was hoping that the pow function would recognize pow(-1,1.2) as ((-1)^6)^(1/5). But it doesn't.

Does anybody know of a c++ library that will recognize these? Perhaps somebody has a decomposition routine they could share.

有帮助吗?

解决方案

It seems like you're looking for pow(abs(x), y).


Explanation: you seem to be thinking in terms of

xy = (xN)(y/N)

If we choose that N === 2, then you have

(x2)y/2 = ((x2)1/2)y

But

(x2)1/2 = |x|

Substituting gives

|x|y

This is a stretch, because the above manipulations only work for non-negative x, but you're the one who chose to use that assumption.

其他提示

Mathematically, pow(-1, 1.2) is simply not defined. There are no powers with fractional exponents of negative numbers, and I hope there is no library that will simply return some arbitray value for such an expression. Would you also expect things like

pow(-1, 0.5) = ((-1)^2)^(1/4) = 1

which obviously isn't desirable.

Moreover, the floating point number 1.2 isn't even exactly equal to 6/5. The closest double precision number to 1.2 is

1.1999999999999999555910790149937383830547332763671875

Given this, what result would you expect now for pow(-1, 1.2)?

If you want to raise negative numbers to powers -- especially fractional powers -- use the cpow() method. You'll need to include <complex> to use it.

Sounds like you want to perform a complex power (cpow()) and then take the magnitude (abs()) of that after.

>>> abs(cmath.exp(1.2*cmath.log(-1)))
1.0
>>> abs(cmath.exp(1.2*cmath.log(-293.2834)))
913.57662451612202

pow(a,b) is often thought of, defined as, and implemented as exp(log(a)*b) where log(a) is natural logarithm of a. log(a) is not defined for a<=0 in real numbers. So you need to either write a function with special case for negative a and integer b and/or b=1/(some_integer). It's easy to special-case for integer b, but for b=1/(some_integer) it's prone to round-off problems, like Sven Marnach pointed out.

Maybe for your domain pow(-a,b) should always be -pow(a,b)? But then you'd just implement such function, so I assume the question warrants more explanation .

Like duskwuff suggested, a much more robust and "mathematical" solution is to use complex functions log and exp, but it's much more "complex" (excuse my pun) than it seems on the surface (even though there's cpow function). And it'll be much slower if you have to compute a lot of pow()s.

Now there's an important catch with complex numbers that may or may not be relevant to your problem domain: when done right, the result of pow(a,b) is not one, but often a few complex numbers, but in the cases you care about, one of them will be complex number with nearly-zero imaginary part (it'll be non-zero due to roundoff errors) which you can simply ignore and/or not compute in your code.

To demonstrate it, consider what pow(-1,.5) is. It's a number X such that X^2==-1. Guess what? There are 2 such numbers: i and -i. Generally, pow(-1, 1/N) has exactly N solutions, although you're interested in only one of them.

If the imaginary part of all results of pow(a,b) is significant, it means you are passing wrong values. For single-precision floating point values in the range you describe, 1e-6*max(abs(a),abs(b)) would be a good starting point for defining the "significant enough" threshold. The extreme "wrong values" would be pow(-1,0.5) which would return 0 + 1i (0 in real part, 1 in imaginary part). Here the imaginary part is huge relative to the input and real part, so you know you screwed up your input values.

In any reasonable single-return-result implementation of cpow() , cpow(-1,0.3333) will probably return something like -1+0.000001i and ignore two other values with significant imaginary parts. So you can just take that real value and that's your answer.

Use std::complex. Without that, the roots of unity don't make much sense. With it they make a whole lot of sense.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top