Reputation:
Math.pow()
, pow()
, whatever it's called, a lot of languages (and calculators) have some built in function to calculate x=a^b for floats (or doubles). There's the special case of a being negative and b not being an integer. Some will return NaN
, others give a complex result (ahem Python). But some are actually capable of giving real results, and so what I'm wondering is how. To explain my confusion:
Suppose b is rational: b=c/d. Now we look at the parity of c and d:
d is even: no real x -> NaN or error
d is odd, c is even: positive x
d is odd, c is odd: negative x
Floats are stored in a particular format that means if it were interpreted literally it would always be an even d (power of 2 actually). There's no way to know the real parity of c and d since that information is lost in computation. It would just have to guess.
So my guess as to what it's doing - it tries to find a rational c/d close to b, with odd d and both c and d less than some threshold t. Smaller t means it can be more sure it's correct but it'll work on less numbers. If that succeeds, it uses the parity of c. Otherwise it pretends d is even. After all, a float can be anything and the math library doesn't want to give a possibly wrong result by assuming it's rational when it might not be.
That's only my guess though. If anyone has actually seen the code in one of these power functions (or a specification, that's just as good) and could provide insight, that'd be great.
Upvotes: 4
Views: 2429
Reputation: 9382
If you are ready to cheat, here is how you can raise a negative to any power:
x^(b/c)=x^(2b/2c)=(x^2b)^(1/2c)
x^2b
is positive, so no problem for taking the 2c-th root
Upvotes: 0
Reputation: 51845
first see: Power by squaring for negative exponents
Now let assume case x^y
where x<0
and y
is not integer. If you use
x^y = exp2(y*log2(x))
then you;re limited by the log2
definition range hence the NaN
or |x|^y
. If you want something better instead you can try to disect y
to this form:
y = a/b
where a,b
are integers. If possible (or if rounding applied) then you change the problem to this:
x^y = (x^a)^(1/b)
so now you can handle more cases (exactly as you suggested):
if a
is even sub-result is no longer negative
as x^a>=0
so (x^a)^(1/b)>=0
if both a,b
are odd result is negative
else result is NaN
or use |x|^y
instead
Now back to your float
question the number is always in this form:
y = mantissa*exp2(exponent)
so yes b
is even (unless exponent!=0
which means number is integer). As mantissa
is stored as an integer you can obtain its parity by inspecting its LSB. Do not forget that in floats
the MSB is missing and always should be 1
unless a special case like de-normalized or Nan/Inf
numbers are present
Upvotes: 1