Столкнувшись с проблемой с использованием переменной в качестве показателя в Джулии - PullRequest
3 голосов
/ 05 октября 2019

Я новичок в Джулии и работал над некоторыми примерами проблем из здесь , чтобы получить представление о языке. Чтобы описать конкретную проблему, с которой я сталкиваюсь. Я пытаюсь написать код для вопроса 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

Ответы [ 2 ]

5 голосов
/ 06 октября 2019

Это характерно для нескольких языков программирования, не только для Джулии: возведение в степень имеет более высокий приоритет, чем вычитание или отрицание. Для Юлии вы можете увидеть таблицу списка приоритетов операторов здесь: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity-1.

По этой причине -1^2 не дает того, что вы наивно ожидаете:

julia> -1^2
-1

InЧтобы переопределить приоритет по умолчанию, просто используйте соответствующие скобки:

julia> (-1)^2
1

Как подсказывает Линдон Уайт в комментарии , хороший способ визуализации приоритета операций в выражениичтобы процитировать его

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

Здесь вы можете заметить, что вВ первом случае возведение в степень выполняется до отрицания, во втором случае, когда используются скобки, отрицание идет до возведения в степень.

Еще один изящный способ увидеть, как в Джулии понижается выражение, - это использовать 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
2 голосов
/ 06 октября 2019

Отвечая на мой собственный вопрос. Похоже, что добавление скобок вокруг -1 решает проблему.

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