ввод: "20+10/5-1*2"
Я хочу выполнить арифметические операции с этой строкой, как я могу это сделать без использования метода eval
в ruby?
ожидаемый результат: 20
ты не можешь. в чем проблема eval
? если у вас есть строка, и вам нужно ее «оценить». eval
это путь. возможно, вам нужно изменить способ получения ввода.
этот вопрос задал интервьюер, он сказал, что не использует метод eval. используйте свою пользовательскую логику. Я пытался, но я не нашел никакого способа.
вы можете разбить строку, возможно, использовать регулярное выражение. конвертируйте числа с помощью to_i
, используйте метод send
для выполнения операций.
Вы должны посмотреть алгоритм маневровой станции для преобразования в обратную польскую нотацию, а затем оценить обратную польскую нотацию.
@ Алекс, я бы сказал, что с использованием eval
возникает серьезная проблема. Представьте, что вместо арифметической операции следующая строка содержит код для отправки ваших ключей ssh во внешний источник или для удаления вашего диска...
@spickermann, конечно, я пытался добраться до сути проблемы. Я полагал, что мы еще не начали производство... пока.
Хотя я не решаюсь ответить на вопрос на собеседовании и меня совершенно смущает этот код, вот один ужасный способ сделать это. Я сделал это только для Ruby и избегал помощников Rails, потому что это казалось больше задачей Ruby, а не задачей Rails.
#
# Evaluate a string representation of an arithmetic formula provided only these operations are expected:
# + | Addition
# - | Subtraction
# * | Multiplication
# / | Division
#
# Also assumes only integers are given for numerics.
# Not designed to handle division by zero.
#
# Example input: '20+10/5-1*2'
# Expected output: 20.0
#
def eval_for_interview(string)
add_split = string.split('+')
subtract_split = add_split.map{ |v| v.split('-') }
divide_split = subtract_split.map do |i|
i.map{ |v| v.split('/') }
end
multiply_these = divide_split.map do |i|
i.map do |j|
j.map{ |v| v.split('*') }
end
end
divide_these = multiply_these.each do |i|
i.each do |j|
j.map! do |k, l|
if l == nil
k.to_i
else
k.to_i * l.to_i
end
end
end
end
subtract_these = divide_these.each do |i|
i.map! do |j, k|
if k == nil
j.to_i
else
j.to_f / k.to_f
end
end
end
add_these = subtract_these.map! do |i, j|
if j == nil
i.to_f
else
i.to_f - j.to_f
end
end
add_these.sum
end
Вот пример вывода:
eval_for_interview('1+1')
=> 2.0
eval_for_interview('1-1')
=> 0.0
eval_for_interview('1*1')
=> 1.0
eval_for_interview('1/1')
=> 1.0
eval_for_interview('1+2-3*4')
=> -9.0
eval_for_interview('1+2-3/4')
=> 2.25
eval_for_interview('1+2*3/4')
=> 2.5
eval_for_interview('1-2*3/4')
=> -0.5
eval_for_interview('20+10/5-1*2')
=> 20.0
eval_for_interview('20+10/5-1*2*4-2/6+12-1-1-1')
=> 31.0
можно ли показать вывод в скобках? как ввод: (5+1)/2 вывод: 3
Я предполагаю, что это возможно, но у меня определенно нет времени писать этот код. Вероятно, было бы проще всего с рекурсией.
есть ли другой способ обойтись без использования eval?