Project

General

Profile

Actions

Bug #17318

closed

Raising float to the power of other issue

Added by deXterbed (Manoj Mishra) about 1 year ago. Updated about 1 year ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:100779]

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 > x*y
=> (-0.48179173935576963+0.012409246172848264i)
2.6.3 :004 > -0.4790529833050308
*0.9918032786885246
=> -0.4819515219418196

Updated by deXterbed (Manoj Mishra) about 1 year ago

Formatting replaced the double * with a single * i put in the snippet above, please ignore

Updated by mame (Yusuke Endoh) about 1 year 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 1 year ago

mame (Yusuke Endoh) wrote in #note-2:

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)

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 1 year 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 1 year 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 1 year 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 1 year 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.

Actions

Also available in: Atom PDF