<p dir="auto">Working with negative exponents has some very odd behaviors, to say the least. Running the internals of the <code class="notranslate">^</code> function gives different results than <code class="notranslate">^</code> itself, evaluation success changes based on whether a variable is replaced with its value, and <code class="notranslate">@code_*</code> forms are convinced that the result should always be of type <code class="notranslate">Int64</code>. Tested on v1.0.0 and v1.1.0-DEV.</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; 2 ^ -5
0.03125

julia&gt; Base.power_by_squaring(2, -5)
ERROR: DomainError with -5:
Cannot raise an integer x to a negative power -5.
Make x a float by adding a zero decimal (e.g., 2.0^-5 instead of 2^-5), or write 1/x^5, float(x)^-5, or (x//1)^-5
Stacktrace:
 [1] throw_domerr_powbysq(::Int64, ::Int64) at ./intfuncs.jl:176
 [2] power_by_squaring(::Int64, ::Int64) at ./intfuncs.jl:196
 [3] top-level scope at none:0

julia&gt; @edit 2 ^ -5
# ^(x::T, p::T) where {T&lt;:Integer} = power_by_squaring(x,p)"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">2</span> <span class="pl-k">^</span> <span class="pl-k">-</span><span class="pl-c1">5</span>
<span class="pl-c1">0.03125</span>

julia<span class="pl-k">&gt;</span> Base<span class="pl-k">.</span><span class="pl-c1">power_by_squaring</span>(<span class="pl-c1">2</span>, <span class="pl-k">-</span><span class="pl-c1">5</span>)
ERROR<span class="pl-k">:</span> DomainError with <span class="pl-k">-</span><span class="pl-c1">5</span><span class="pl-k">:</span>
Cannot raise an integer x to a negative power <span class="pl-k">-</span><span class="pl-c1">5.</span>
Make x a float by adding a zero decimal (e<span class="pl-k">.</span>g., <span class="pl-c1">2.0</span><span class="pl-k">^-</span><span class="pl-c1">5</span> instead of <span class="pl-c1">2</span><span class="pl-k">^-</span><span class="pl-c1">5</span>), or write <span class="pl-c1">1</span><span class="pl-k">/</span>x<span class="pl-k">^</span><span class="pl-c1">5</span>, <span class="pl-c1">float</span>(x)<span class="pl-k">^-</span><span class="pl-c1">5</span>, or (x<span class="pl-k">//</span><span class="pl-c1">1</span>)<span class="pl-k">^-</span><span class="pl-c1">5</span>
Stacktrace<span class="pl-k">:</span>
 [<span class="pl-c1">1</span>] <span class="pl-c1">throw_domerr_powbysq</span>(<span class="pl-k">::</span><span class="pl-c1">Int64</span>, <span class="pl-k">::</span><span class="pl-c1">Int64</span>) at <span class="pl-k">./</span>intfuncs<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">176</span>
 [<span class="pl-c1">2</span>] <span class="pl-c1">power_by_squaring</span>(<span class="pl-k">::</span><span class="pl-c1">Int64</span>, <span class="pl-k">::</span><span class="pl-c1">Int64</span>) at <span class="pl-k">./</span>intfuncs<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">196</span>
 [<span class="pl-c1">3</span>] top<span class="pl-k">-</span>level scope at none<span class="pl-k">:</span><span class="pl-c1">0</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">@edit</span> <span class="pl-c1">2</span> <span class="pl-k">^</span> <span class="pl-k">-</span><span class="pl-c1">5</span>
<span class="pl-c"><span class="pl-c">#</span> ^(x::T, p::T) where {T&lt;:Integer} = power_by_squaring(x,p)</span></pre></div>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; x = -2;

julia&gt; x ^ x
ERROR: DomainError with -2:
Cannot raise an integer x to a negative power -2.
Make x a float by adding a zero decimal (e.g., 2.0^-2 instead of 2^-2), or write 1/x^2, float(x)^-2, or (x//1)^-2
Stacktrace:
 [1] throw_domerr_powbysq(::Int64, ::Int64) at ./intfuncs.jl:176
 [2] power_by_squaring(::Int64, ::Int64) at ./intfuncs.jl:196
 [3] ^(::Int64, ::Int64) at ./intfuncs.jl:220
 [4] top-level scope at none:0

julia&gt; x ^ (-2)
0.25

julia&gt; (-2) ^ x
ERROR: DomainError with -2:
Cannot raise an integer x to a negative power -2.
Make x a float by adding a zero decimal (e.g., 2.0^-2 instead of 2^-2), or write 1/x^2, float(x)^-2, or (x//1)^-2
Stacktrace:
 [1] throw_domerr_powbysq(::Int64, ::Int64) at ./intfuncs.jl:176
 [2] power_by_squaring(::Int64, ::Int64) at ./intfuncs.jl:196
 [3] ^(::Int64, ::Int64) at ./intfuncs.jl:220
 [4] top-level scope at none:0

julia&gt; (-2) ^ (-2)
0.25

julia&gt; @code_warntype x ^ x
Body::Int64
220 1 ─ %1 = invoke Base.power_by_squaring(_2::Int64, _3::Int64)::Int64                                          │
    └──      return %1                                                                                           │"><pre class="notranslate">julia<span class="pl-k">&gt;</span> x <span class="pl-k">=</span> <span class="pl-k">-</span><span class="pl-c1">2</span>;

julia<span class="pl-k">&gt;</span> x <span class="pl-k">^</span> x
ERROR<span class="pl-k">:</span> DomainError with <span class="pl-k">-</span><span class="pl-c1">2</span><span class="pl-k">:</span>
Cannot raise an integer x to a negative power <span class="pl-k">-</span><span class="pl-c1">2.</span>
Make x a float by adding a zero decimal (e<span class="pl-k">.</span>g., <span class="pl-c1">2.0</span><span class="pl-k">^-</span><span class="pl-c1">2</span> instead of <span class="pl-c1">2</span><span class="pl-k">^-</span><span class="pl-c1">2</span>), or write <span class="pl-c1">1</span><span class="pl-k">/</span>x<span class="pl-k">^</span><span class="pl-c1">2</span>, <span class="pl-c1">float</span>(x)<span class="pl-k">^-</span><span class="pl-c1">2</span>, or (x<span class="pl-k">//</span><span class="pl-c1">1</span>)<span class="pl-k">^-</span><span class="pl-c1">2</span>
Stacktrace<span class="pl-k">:</span>
 [<span class="pl-c1">1</span>] <span class="pl-c1">throw_domerr_powbysq</span>(<span class="pl-k">::</span><span class="pl-c1">Int64</span>, <span class="pl-k">::</span><span class="pl-c1">Int64</span>) at <span class="pl-k">./</span>intfuncs<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">176</span>
 [<span class="pl-c1">2</span>] <span class="pl-c1">power_by_squaring</span>(<span class="pl-k">::</span><span class="pl-c1">Int64</span>, <span class="pl-k">::</span><span class="pl-c1">Int64</span>) at <span class="pl-k">./</span>intfuncs<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">196</span>
 [<span class="pl-c1">3</span>] <span class="pl-k">^</span>(<span class="pl-k">::</span><span class="pl-c1">Int64</span>, <span class="pl-k">::</span><span class="pl-c1">Int64</span>) at <span class="pl-k">./</span>intfuncs<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">220</span>
 [<span class="pl-c1">4</span>] top<span class="pl-k">-</span>level scope at none<span class="pl-k">:</span><span class="pl-c1">0</span>

julia<span class="pl-k">&gt;</span> x <span class="pl-k">^</span> (<span class="pl-k">-</span><span class="pl-c1">2</span>)
<span class="pl-c1">0.25</span>

julia<span class="pl-k">&gt;</span> (<span class="pl-k">-</span><span class="pl-c1">2</span>) <span class="pl-k">^</span> x
ERROR<span class="pl-k">:</span> DomainError with <span class="pl-k">-</span><span class="pl-c1">2</span><span class="pl-k">:</span>
Cannot raise an integer x to a negative power <span class="pl-k">-</span><span class="pl-c1">2.</span>
Make x a float by adding a zero decimal (e<span class="pl-k">.</span>g., <span class="pl-c1">2.0</span><span class="pl-k">^-</span><span class="pl-c1">2</span> instead of <span class="pl-c1">2</span><span class="pl-k">^-</span><span class="pl-c1">2</span>), or write <span class="pl-c1">1</span><span class="pl-k">/</span>x<span class="pl-k">^</span><span class="pl-c1">2</span>, <span class="pl-c1">float</span>(x)<span class="pl-k">^-</span><span class="pl-c1">2</span>, or (x<span class="pl-k">//</span><span class="pl-c1">1</span>)<span class="pl-k">^-</span><span class="pl-c1">2</span>
Stacktrace<span class="pl-k">:</span>
 [<span class="pl-c1">1</span>] <span class="pl-c1">throw_domerr_powbysq</span>(<span class="pl-k">::</span><span class="pl-c1">Int64</span>, <span class="pl-k">::</span><span class="pl-c1">Int64</span>) at <span class="pl-k">./</span>intfuncs<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">176</span>
 [<span class="pl-c1">2</span>] <span class="pl-c1">power_by_squaring</span>(<span class="pl-k">::</span><span class="pl-c1">Int64</span>, <span class="pl-k">::</span><span class="pl-c1">Int64</span>) at <span class="pl-k">./</span>intfuncs<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">196</span>
 [<span class="pl-c1">3</span>] <span class="pl-k">^</span>(<span class="pl-k">::</span><span class="pl-c1">Int64</span>, <span class="pl-k">::</span><span class="pl-c1">Int64</span>) at <span class="pl-k">./</span>intfuncs<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">220</span>
 [<span class="pl-c1">4</span>] top<span class="pl-k">-</span>level scope at none<span class="pl-k">:</span><span class="pl-c1">0</span>

julia<span class="pl-k">&gt;</span> (<span class="pl-k">-</span><span class="pl-c1">2</span>) <span class="pl-k">^</span> (<span class="pl-k">-</span><span class="pl-c1">2</span>)
<span class="pl-c1">0.25</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">@code_warntype</span> x <span class="pl-k">^</span> x
Body<span class="pl-k">::</span><span class="pl-c1">Int64</span>
<span class="pl-c1">220</span> <span class="pl-c1">1</span> ─ <span class="pl-k">%</span><span class="pl-c1">1</span> <span class="pl-k">=</span> invoke Base<span class="pl-k">.</span><span class="pl-c1">power_by_squaring</span>(_2<span class="pl-k">::</span><span class="pl-c1">Int64</span>, _3<span class="pl-k">::</span><span class="pl-c1">Int64</span>)<span class="pl-k">::</span><span class="pl-c1">Int64</span>                                          │
    └──      <span class="pl-k">return</span> <span class="pl-k">%</span><span class="pl-c1">1</span>                                                                                           │</pre></div>
<p dir="auto">As discussed in <a href="https://discourse.julialang.org/t/confusing-difference-literal-vs-variable/13515/5" rel="nofollow">https://discourse.julialang.org/t/confusing-difference-literal-vs-variable/13515/5</a> it would be good if this is documented somewhere. The explanation of <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/StefanKarpinski/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/StefanKarpinski">@StefanKarpinski</a> in this thread will be helpful:</p>
<blockquote>
<p dir="auto">This was a controversial change and there are still many people who are not entirely comfortable with it. The starting point is that people do not really often expect or want x^2 and x^-1 to be pow(x, 2) and pow(x, -1), respectively. Rather, people want x^2 to be syntax for x<em>x. The latter can generally be implemented much more efficiently than calling a general power function. With sufficiently clever optimizations (constant propagation + power reduction), one can potentailly optimize pow(x, 2) into x</em>x but it would be even better if we didn’t have to do such a clever optimization in the first place. It’s been a fairly common and successful strategy in the design of Julia to arrange things so that you can get great performance in a straightforward way without need for clever optimizations instead of trying to make the optimizers smarter. So what this design does is it causes x^n where n is a literal integer value to call Base.literal_pow(x, Val(n)), which allows us to specialize the syntax on individual literal values like 2 or -1. This allow us to make x^2 actually mean x*x instead of needing to try to optimize it to that. It also allows us to make negative literal exponents work without introducing a type instability in the general ^ function. And indeed, we used to get regular complaints from new users that 2^-1 doesn’t return 0.5 as they would expect, instead giving them a domain error because of the negative exponent. There are good reasons for it but users don’t care about involved language design reasons, they just want it to work. A way to think about this is that ^2 is its own operator, as is ^3 and ^-1, and so on. Hopefully that helps.</p>
</blockquote>
<p dir="auto"><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="267279366" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/24240" data-hovercard-type="pull_request" data-hovercard-url="/JuliaLang/julia/pull/24240/hovercard" href="https://github.com/JuliaLang/julia/pull/24240">#24240</a></p>