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) almost 5 years ago
          Updated by deXterbed (Manoj Mishra) almost 5 years ago
          
          
        
        
      
      Formatting replaced the double * with a single * i put in the snippet above, please ignore
        
           Updated by mame (Yusuke Endoh) almost 5 years ago
          Updated by mame (Yusuke Endoh) almost 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) almost 5 years ago
          Updated by deXterbed (Manoj Mishra) almost 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) almost 5 years ago
          Updated by Dan0042 (Daniel DeLorme) almost 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) almost 5 years ago
          Updated by mame (Yusuke Endoh) almost 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) almost 5 years ago
          Updated by phluid61 (Matthew Kerwin) almost 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) almost 5 years ago
          Updated by gotoken (Kentaro Goto) almost 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.