In Haskell, I have tried to find the cube root of a negative integer, for example, -1, without success.
I have used (-1) ** (1/3), but this returns a NaN. I thought that this might have something to do with type of the (1/3) fraction, but using (1/3 :: Double) yielded no success either.
As a result, my question is how can one find the cube root of -1 using Haskell so that it doesn't return NaN?
For real numbers, the Haskell operator (**) is only defined for negative base (left-hand side) values when the exponent (right-hand side) is integer-valued. If this strikes you as strange, note that the C function pow behaves the same way:
printf("%f\n", pow(-1.0, 1.0/3.0)); // prints "-nan", for me
and so does Python's ** operator:
print((-1.0)**(1.0/3.0))
# gives: ValueError: negative number cannot be raised to fractional power
The problem is partially a mathematical one. The "correct answer" for raising a negative base to a non-integral power is far from obvious. See, for example, this question on the Mathematics SO.
If you only need a cube root that can handle negative numbers, the other answers given should work fine, except that @Istvan's answer should use signum instead of sign, like this:
cbrt x = signum x * abs x ** (1/3)
If you want a more general integral root function for real numbers, be warned that for even n, there are no nth roots of negative numbers that are real, so this is about the best you can do:
-- | Calculate nth root of b
root :: (Integral n, RealFloat b) => n -> b -> b
root n b | odd n && b < 0 = - abs b ** overn
| otherwise = b ** overn
where overn = 1 / fromIntegral n
This gives:
> root 3 (-8)
-2.0
> root 4 (-8)
NaN -- correct, as no real root exists
>
I don't know Haskell, but you can do something like this: sign(x) * abs(x) ** (1/3)
On ghci I've done something that seems to solve your problem:
let cbrt x = if x < 0 then -((-x) ** (1/3)) else x ** (1/3)
A simple cuberoot function.
As I'm still learning I don't know if this is a proper solution, so please let me know if there's something missing or wrong ;)
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