Running into an issue with using a variable as an exponent in Julia

Viewed 153

I am new to Julia and was working on some example problems from here as a way of getting a handle on the language. To describe the specific issue I'm facing. I am trying to write some code for question 11 in the programming problems which requires me to compute a summation. I am reproducing my code below. I set a variable k to 1 and the formula needs to find the value of -1 to the power of k + 1. When k = 1, it should compute the result as -1 squared which should be 1 but it returns -1. Not sure what is going wrong here. Help me understand my error?

function computeequation()
    result = 0
    for k = 1:1000000
        result = result + ((-1^(k+1))/((2 * k) - 1))
    end
    return 4 * result
end
2 Answers

This is common to several programming languages, not just Julia: exponentiation has a higher precedence than subtraction or negation. For Julia, you can see the list table of operator precedence here: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity-1.

For this reason, -1^2 doesn't produce what you may naively expect:

julia> -1^2
-1

In order to override the default precedence, just use parentheses as appropriate:

julia> (-1)^2
1

As suggested by Lyndon White in a comment, a nice way to visualise the precedence of operations in an expression is to quote it

julia> :(-1 ^ 2)
:(-(1 ^ 2))

julia> :((-1) ^ 2)
:((-1) ^ 2)

and dump it to see the full AST:

julia> dump(:(-1 ^ 2))
Expr
  head: Symbol call
  args: Array{Any}((2,))
    1: Symbol -
    2: Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol ^
        2: Int64 1
        3: Int64 2

julia> dump(:((-1) ^ 2))
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol ^
    2: Int64 -1
    3: Int64 2

Here you can note that in the first case the exponentiation is done before the negation, in the second case where parentheses are used, negation comes before exponentiation.

Another neat way to see how an expression is lowered in Julia is to use the Meta.lower function:

julia> Meta.lower(Main, :(-1 ^ 2) )
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope'
1 ─ %1 = Core.apply_type(Base.Val, 2)
│   %2 = (%1)()
│   %3 = Base.literal_pow(^, 1, %2)
│   %4 = -%3
└──      return %4
))))

julia> Meta.lower(Main, :((-1) ^ 2) )
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope'
1 ─ %1 = Core.apply_type(Base.Val, 2)
│   %2 = (%1)()
│   %3 = Base.literal_pow(^, -1, %2)
└──      return %3
))))

For your particular problem you can do

function computeequation()
    result = 0
    for k = 1:1000_000
        result = result + ((-1) ^ (k + 1))/((2 * k) - 1)
    end
    return 4 * result
end

Answering my own question. Looks like adding braces around the -1 solves the problem.

function computeequation()
    result = 0
    for k = 1:1000000
        result = result + (((-1)^(k+1))/((2 * k) - 1))
    end
    return 4 * result
end
Related