R seems pretty comfortable with computing the odd root of a negative number
-0.2^(1/3) # returns a good number
# [1] -0.5848035
but something weird happens if you raise a vector to the 1/3.
c(-0.2, 1)^(1/3) # returns an NA for the first element
# [1] NaN 1
I'm interested in an answer that explains what is happening differently to the vector than to the negative value when provided as a numeric scalar.
I'm not looking for a workaround e.g. function(x){sign(x)*(abs(x))^(1/3)}. This answer seems to point in a good direction... how does the "^" operator think differently about vectors and scalars?
I'm not looking for a workaround e.g.
function(x) {sign(x) * (abs(x)) ^ (1/3)}.
I'm interested in an answer that explains what is happening differently to the vector than to the negative value when provided as a numeric scalar.
how does the
^operator think differently about vectors and scalars?
You seem to believe that c(-0.2, 1)^(1/3) translates to c(-0.2^(1/3), 1^(1/3)). This is incorrect. Operator ^ is actually a function, that is, (a) ^ (b) is as same as "^"(a, b). Therefore, the correct interpretation goes as follows:
c(-0.2, 1)^(1/3)
=> "^"(c(-0.2, 1), 1/3)
=> c( "^"(-0.2, 1/3), "^"(1, 1/3) )
=> c( (-0.2)^(1/3), (1)^(1/3) )
=> c( NaN, 1 )
Now, why doesn't -0.2^(1/3) give NaN? Because ^ has higher operation precedence than +, -, * and /. So as it is written, it really implies -(0.2^(1/3)) instead of (-0.2)^(1/3).
The lesson is that, to avoid buggy code, write your code as (a) ^ (b) instead of just a ^ b.
Additional Remark:
I often compare ^ and : when teaching R to my students, because they have different behaviors. But they all show the importance of protecting operands with brackets.
(-1):2
#[1] -1 0 1 2
-1:2
#[1] -1 0 1 2
-(1:2)
#[1] -1 -2
2*3:10
#[1] 6 8 10 12 14 16 18 20
(2*3):10
#[1] 6 7 8 9 10
2*(3:10)
#[1] 6 8 10 12 14 16 18 20
See ?Syntax for details of operator precedence.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With