【问题标题】:Running into an issue with using a variable as an exponent in Julia在 Julia 中使用变量作为指数时遇到问题
【发布时间】:2019-10-05 20:46:58
【问题描述】:

我是 Julia 的新手,正在处理来自 here 的一些示例问题,以作为掌握该语言的一种方式。描述我面临的具体问题。我正在尝试为编程问题中的问题 11 编写一些代码,这需要我计算总和。我在下面复制我的代码。我将变量 k 设置为 1,公式需要找到 -1 的 k + 1 次方的值。当 k = 1 时,它应该将结果计算为 -1 的平方,它应该是 1,但它返回 -1。不知道这里出了什么问题。帮助我理解我的错误?

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

【问题讨论】:

    标签: julia exponent


    【解决方案1】:

    这在几种编程语言中很常见,不仅仅是 Julia:求幂比减法或求反具有更高的优先级。对于 Julia,您可以在此处查看运算符优先级列表:https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity-1

    因此,-1^2 不会产生您可能天真的期望的结果:

    julia> -1^2
    -1
    

    为了覆盖默认优先级,只需根据需要使用括号:

    julia> (-1)^2
    1
    

    正如 Lyndon White 在 a comment 中所建议的那样,可视化表达式中操作优先级的一种好方法是引用它

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

    dump 可以看到完整的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
    

    这里你可以注意到,在第一种情况下,求幂在求反之前进行,在使用括号的第二种情况下,求反在求幂之前。

    在 Julia 中查看表达式如何降低的另一种巧妙方法是使用 Meta.lower 函数:

    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
    ))))
    

    对于您的特定问题,您可以这样做

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

    【讨论】:

    • 而不是使用 Meta.lower 我会引用它并转储 AST,它将包含所有分组。您想将其添加到您的答案中吗?
    【解决方案2】:

    回答我自己的问题。看起来像在 -1 周围添加大括号可以解决问题。

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

    【讨论】:

      猜你喜欢
      • 2022-01-04
      • 1970-01-01
      • 2020-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多