Known Ruby Bug?

Ovid on 2009-02-20T22:08:47

I suppose I should ask this in a Ruby forum, but since I'm so used to slinging other languages here ...

To find the Nth root of number is simple: raise the number to the reciprocal of N. For example, to find the cube root of 8:

$ perl -le 'print 8 ** (1/3)'
2

But you can't quite do that in Ruby:

$ ruby -e 'puts 8 ** (1/3)'
1

But this is a "feature", not a bug (*cough*) because the 1/3 is considered integer math and evaluates to 0, leaving you with 8 to the 0th power. Anything raised to the power of 0 results in 1. So far so good.

So to force floating point math, use a floating point number:

$ ruby -e 'puts 8 ** (1/3.0)'
2

And all is good. Except ...

Let's take the square root of 1:

$ ruby -e 'puts 1 ** (1/2.0)'
1.0

Now let's take the square root of -1:

$ ruby -e 'puts -1 ** (1/2.0)'
-1.0

Huh? The square root of -1 is imaginary (or i, if you want to be specific). What's going on here?

Yes, I know about Math.sqrt, which at least thoughtfully throws an exception rather than give an incorrect value:

$ ruby -e 'puts Math.sqrt(-1)'
-e:1:in `sqrt': Numerical argument out of domain - sqrt (Errno::EDOM)
	from -e:1


Precedence

Simon on 2009-02-20T23:13:33

simon@alibi ~ % ruby -e 'puts -1 ** 0.5'
-1.0
simon@alibi ~ % ruby -e 'puts ( (-1) ** 0.5)'
NaN

Perl is better?

frew on 2009-02-21T00:38:28

FrewSchmidt2 [9844] % perl -le 'print (-1) ** (1/2)'
-1

Am I missing something here?

Re:Perl is better?

Burak on 2009-02-21T01:07:07

indeed you are:

C:\Users\burak>perl -MO=Deparse -le "print (-1) ** (1/2)"
BEGIN { $/ = "\n"; $\ = "\n"; }
print(-1) ** 0.5;
-e syntax OK

try this instead:

print( (-1) ** (1/2) )

Re:Perl is better?

frew on 2009-02-21T01:13:36

Hah! The funny thing is that I was talking to someone about this bug YESTERDAY.

Thanks.

Re:Perl is better?

garu on 2009-02-21T03:10:48

Ruby is no worse either, then:

$ ruby -e 'puts ((-1) ** (1/2.0))'
NaN

Re:Perl is better?

drhyde on 2009-02-23T12:21:17

Having to liberally splatter brackets around the place looks no better than having to force something to not be interpreted as an integer. It's certainly just as obscure.