Невоспроизводимое сравнение строк, приводящее к сбою elsif
-
06-09-2019 - |
Вопрос
Отвечая этот вопрос о коде для гольфа, Я столкнулся с проблемой в своем ответе.
Я тестировал это, и я даже не могу заставить эти два сравнения работать в коде, несмотря на то, что IRB имеет правильное поведение.Я в самом деле здесь нужна некоторая помощь.
Вот код, ниже которого будет объяснение проблемы.
def solve_expression(expr)
chars = expr.split '' # characters of the expression
parts = [] # resulting parts
s,n = '','' # current characters
while(n = chars.shift)
if (s + n).match(/^(-?)[.\d]+$/) || (!chars[0].nil? && chars[0] != ' ' && n == '-') # only concatenate when it is part of a valid number
s += n
elsif (chars[0] == '(' && n[0] == '-') || n == '(' # begin a sub-expression
p n # to see what it breaks on, ( or -
negate = n[0] == '-'
open = 1
subExpr = ''
while(n = chars.shift)
open += 1 if n == '('
open -= 1 if n == ')'
# if the number of open parenthesis equals 0, we've run to the end of the
# expression. Make a new expression with the new string, and add it to the
# stack.
subExpr += n unless n == ')' && open == 0
break if open == 0
end
parts.push(negate ? -solve_expression(subExpr) : solve_expression(subExpr))
s = ''
elsif n.match(/[+\-\/*]/)
parts.push(n) and s = ''
else
parts.push(s) if !s.empty?
s = ''
end
end
parts.push(s) unless s.empty? # expression exits 1 character too soon.
# now for some solutions!
i = 1
a = parts[0].to_f # left-most value is will become the result
while i < parts.count
b,c = parts[i..i+1]
c = c.to_f
case b
when '+': a = a + c
when '-': a = a - c
when '*': a = a * c
when '/': a = a / c
end
i += 2
end
a
end
Проблема возникает при назначении negate
.
Мне нужно, чтобы значение negate было истинным, когда символом непосредственно перед выражением является тире, но условие даже не работает.И то , и другое n == '-'
и n[0] == '-'
, форма цитаты не имеет значения, каждый раз получается ЛОЖНАЯ.Тем не менее, я использовал это точное сравнение и n == '('
работает корректно каждый раз!
Что вообще происходит?Почему бы и нет n == '-'
работать, когда n == '('
делает?Это закодировано в UTF-8 без спецификации, UNIX для прерывания строк.
Что не так с моим кодом?
Решение
У вас есть:
if (s + n).match(/^(-?)[.\d]+$/) || (!chars[0].nil? && chars[0] != ' ' && n == '-')
s += n
elsif (chars[0] == '(' && n[0] == '-') || n == '('
Как n
всегда является односимвольной строкой, если (chars[0] == '(' && n[0] == '-'))
является истинным, тогда выполняется предыдущее условие, (!chars[0].nil? && chars[0] != ' ' && n == '-')
, тоже будет правдой.Ваш код никогда не войдет во вторую часть if
если n[0]=='-'
.
Если ваш p n
строка выводит тире, убедитесь, что это точно тот же символ, который вы ищете, а не какой-то символ, который выглядит как прочерк.В Юникоде есть много видов тире, возможно, у вас есть странный символ тире в юникоде в вашем коде или при вводе.