Bug #17318
closedRaising float to the power of other issue
Description
Raising a negative float to another float results in a complex number. Interestingly, doing the same thing without using variables works fine!
Sample Snippet:
$ irb
2.6.3 :001 > x=-0.4790529833050308
=> -0.4790529833050308
2.6.3 :002 > y=0.9918032786885246
=> 0.9918032786885246
2.6.3 :003 > xy
=> (-0.48179173935576963+0.012409246172848264i)
2.6.3 :004 > -0.47905298330503080.9918032786885246
=> -0.4819515219418196
Updated by deXterbed (Manoj Mishra) about 5 years ago
Formatting replaced the double * with a single * i put in the snippet above, please ignore
Updated by mame (Yusuke Endoh) about 5 years ago
- Status changed from Open to Rejected
It is due to precedence of operators unary minus and **.
x**y calculates (-0.4790529833050308)**0.9918032786885246, and -0.4790529833050308**0.9918032786885246 calculates -(0.4790529833050308**0.9918032786885246).
irb(main):001:0> -(0.4790529833050308**0.9918032786885246)
=> -0.4819515219418196
irb(main):002:0> (-0.4790529833050308)**0.9918032786885246
=> (-0.48179173935576963+0.012409246172848266i)
Updated by deXterbed (Manoj Mishra) about 5 years ago
mame (Yusuke Endoh) wrote in #note-2:
It is due to precedence of operators unary minus and
**.
x**ycalculates(-0.4790529833050308)**0.9918032786885246, and-0.4790529833050308**0.9918032786885246calculates-(0.4790529833050308**0.9918032786885246).irb(main):001:0> -(0.4790529833050308**0.9918032786885246) => -0.4819515219418196 irb(main):002:0> (-0.4790529833050308)**0.9918032786885246 => (-0.48179173935576963+0.012409246172848266i)
Thanks for the explanation Yusuke Endoh,
that still raises the question, how exactly am i supposed to calculate x**y without ending up with a complex number? x and y are dynamic values, i can't use parentheses to force precedence. I could use "abs" method but shouldn't this be the default behaviour?
def raise(a, b)
return -((a.abs)**b) if a < 0
a**b
end
Updated by Dan0042 (Daniel DeLorme) about 5 years ago
Also see #16677 w/r edge cases.
-0.4**0.9 #=> -0.4383832905540869
-0.4.to_f**0.9 #=> (-0.416927285116376+0.13546788683122327i)
-(0.4).to_f**0.9 #=> -0.4383832905540869
Updated by mame (Yusuke Endoh) about 5 years ago
deXterbed (Manoj Mishra) wrote in #note-3:
def raise(a, b) return -((a.abs)**b) if a < 0 a**b end
I don't think that this should be the default behavior because raise(-1, 2) returns -1 but I expect the square of -1 to be 1.
Updated by phluid61 (Matthew Kerwin) about 5 years ago
deXterbed (Manoj Mishra) wrote in #note-3:
that still raises the question, how exactly am i supposed to calculate x**y without ending up with a complex number?
Don't raise a negative number to a non-Integer power. That's just maths.
Updated by gotoken (Kentaro Goto) about 5 years ago
That depends on your purpose or background of the problem. In non-math situations, power(a, b) should not return any ordinary number for given a<0 where power(a, b) stands for "a to the power of b" over real, just identical to your notation raise(a, b). In such cases, so the function may raise an exception or returns float::NAN if a<0 or a==0 && b==0 held.