Stefan van der Walt wrote:
> Hi all,
>
> Currently, the power function returns '0' for negative powers of
> integers:
>
> In [1]: N.power(3,-2)
> Out[1]: 0
>
> (or, more confusingly)
>
> In [1]: N.power(a,b)
> Out[1]: 0
>
> which is almost certainly not the answer you want. Two possible
> solutions may be to upcast the input to float before calculation, or
> to return nan.
>
Returning nan seems silly. There really is a result, or rather two
possible results on a tad more sensible than the other. If we were going
to punt it makes more sense to raise an exception, but I doubt that's
necessary. In addition, nan is really a floating point value; if we're
going to return a floating point value, not an integer, we might as well
return the actual result.
> This would be consistent with a function like sqrt:
>
> In [10]: N.sqrt(3)
> Out[10]: 1.7320508075688772
>
> In [11]: N.sqrt(-3)
> Out[11]: nan
>
> Does anyone have an opinion on whether the change is necessary, and if
> so, on which one would work best?
>
This is a complicated tangle of worms. First off there's both "a**b" and
"power(a, b)". These don't necessarily need to work the same. In fact
they already differ somewhat in that a**b does some optimization when b
is a small scalar that power does not (I think anyway -- haven't looked
at this a while). However, if having them differ in any significant way
is likely to be quite confusing, so it should be only be considered if
there's some compelling reason to support multiple behaviors here.
There is a solution that is, IMO, simple obvious and not quite right.
That is to return floats if the b contains any negative numbers while
returning integers otherwise. That sounds appealing at first, but will
cause confusion and memory blow ups when one suddenly has all of ones
arrays become floats because somewhere or other a negative value crept
into an exponent. It's fine for the return type to depend on the types
of the arguments, it's not so good for it to depends on the values. This
restriction gets a little weaker once future division arrives since ints
and floats will be closer to indistinguishable, but it still has some
force. On the other hand, this is consistent with the rest of Python's
behavior.
Another path is to just always return floats from power. One down side
of this is that we lose the ability to do true integer powers, which is
sometimes useful. A second downside is that it introduces a
inconsistency with Python's scalar 'x**y'. One way to finesse both of
these issues is to make numpy.power consistent with math.pow; that is,
it returns floating point values when passed integers. At the same time,
make a**b consistent with the python's '**' operator in that any
negative exponents trigger a floating point return values. This isn't
perfect, but it's as close to a self consistent solution as I can think of.
That's my two cents.
-tim
|