# Rational ^ Rational

Why does this make a Float64 instead of a Rational?

``````julia> ((2//1)^(-4//1))
0.0625
``````

Is this the only way to get a Rational out of exponentiation?

``````julia> Rational((2//1)^(-4//1))
1//16
``````
1 Like

This is the method being called:

``````^(x::Number, y::Rational) = x^(y.num/y.den)
``````

I suppose the thinking is that you probably donâ€™t want this:

``````a = 2 // 1
b = -3 // 8

julia> Rational(a ^ b)
6945500098633947//9007199254740992
``````

Rational to the power of rational is typically irrational:

``````julia> (2//1)^(1//2)
1.4142135623730951
``````
6 Likes

An important principle in Julia to ensure performance, is type stability. I.e. the type of a functionâ€™s return value should be a function of the input types. The return type should not vary with the input values, only with their types. Some powers with rational numbers will yield a rational result, but most often it does not. To ensure type stability the `Rational{Int64} ^ Rational{Int64}` operation returns a `Float64`. Itâ€™s a design choice (it could have been `BigFloat` or `Float32` or whatever, but it is `Float64`).

1 Like

And note that `Rational ^ Integer` is a `Rational`.

``````julia> ((2//1)^(-4))
1//16
``````
2 Likes

Depending on types you get Float46 (reasonable) or BigFloat (also reasonable), and you can do (but itâ€™s not reasonable):

``````julia> Rational(big(1//2)^big(1//2))  # scroll to right to see this is still a "Rational", type that is
81877371507464127617551201542979628307507432471243237061821853600756754782485//115792089237316195423570985008687907853269984665640564039457584007913129639936
``````

`Rational` there implies you get a rational out, but thatâ€™s wrong, as the calculated value an irrational number (so I would avoid typing that in code), you only get the most accurate (considering default precision of BigFloat) rational of the resulting BigFloat number, which was already an approximation.

Since you know the result in in general, for a^b, irrational, i.e. none of the approximations are accurate, then this is more reasonable, if you only want some rational approximation:

``````julia> rationalize(big(1//2)^big(1//2))
4866752642924153522//6882627592338442563
``````

Yes, the type you get is still a Rational, but look at the help string for rationalize, then itâ€™s clear itâ€™s an approximation. I would still just keep the Float64 (or even convert BigFloat to Float64 too).

Or maybe even:

``````julia> rationalize(Int16, big(1//2)^big(1//2))  # possibly rather Rational{Int64}(rationalize(Int16, big(1//2)^big(1//2)))
13860//19601
``````
1 Like