我正在尝试编写一个将字符串作为输入的计算器,例如"2+4-7/2"
,并计算它。它应该处理操作的顺序。
string = '1+1'
module Simple_calculator
class << self
def calculate(string)
operators = [:+, :-, :*, :/]
res = string
operators.each do |op|
splits = string.split(op.to_s)
if splits.size > 1
resMap = splits.map do |sp|
calculate(sp)
end
resMap.map(&:to_f).inject(op)
end
end
res.to_f
end
end
end
我的代码中出错了什么?
答案 0 :(得分:1)
我的代码中出错了什么?
您可以通过运算符拆分字符串,例如:
"1+2+3".split("+")
#=> ["1", "2", "3"]
这看起来是错误的做法。加法,减法,乘法和除法是二进制操作,即它们组合两个元素(操作数),而不是 n 元素。
在您的代码中,1 + 2 + 3被视为:
+
/|\
1 2 3
这使得组合(不同操作的结果)变得更加困难。
更容易对待1 + 2 + 3,如:
+ +
/ \ / \
1 + or + 3
/ \ / \
2 3 1 2
显然,这可以使用递归来解决。这是一个非常基本的解析器/计算器:
def parse(string)
case string
when /(.*)\+(.*)/ then parse($1) + parse($2)
when /(.*)\*(.*)/ then parse($1) * parse($2)
when /^(\d+)$/ then $1.to_i
else
raise SyntaxError
end
end
规则很简单:
/(.*)\+(.*)/
匹配a+b
并返回parse(a) + parse(b)
/(.*)\*(.*)/
匹配a*b
并返回parse(a) * parse(b)
/^(\d+)$/
匹配或更多数字并返回相应的整数SyntaxError
请注意,a
和b
可以是任何内容,而不仅仅是数字。
数字变成数字(第3和第34条;规则&#34;):
parse("1")
#=> "1".to_i
#=> 1
parse("123")
#=> "123".to_i
#=> 123
a+b
评估为parse(a) + parse(b)
:
parse("3+4")
#=> parse("3") + parse("4")
#=> "3".to_i + "4".to_i
#=> 3 + 4
#=> 7
a+b*c
评估为:
parse("1+2*3")
#=> parse("1") + parse("2*3")
#=> "1".to_i + parse("2*3")
#=> 1 + parse("2*3")
#=> 1 + parse("2") * parse("3")
#=> 1 + "2".to_i * parse("3")
#=> 1 + 2 * parse("3")
#=> 1 + 2 * "3".to_i
#=> 1 + 2 * 3
#=> 1 + 6
#=> 7
操作顺序取决于匹配顺序。 a+b
之前的a*b
匹配,因此:
parse("2*3+1")
#=> parse("2*3") + parse("1")
#=> parse("2*3") + parse("1")
#=> parse("2*3") + parse("1")
#=> parse("2") * parse("3") + parse("1")
#=> "2".to_i * parse("3") + parse("1")
#=> 2 * parse("3") + parse("1")
#=> 2 * "3".to_i + parse("1")
#=> 2 * 3 + parse("1")
#=> 6 + parse("1")
#=> 6 + "1".to_i
#=> 6 + 1
#=> 7
答案 1 :(得分:0)
嘿,你输入的是输入而不是结果。这是您的计算方法的快速修复。它的工作但仍然需要重建,因为你可以解析字符串以先找到运算符然后使用它而不是尝试计算所有运算符。
def calculate(string)
operators = [:+, :-, :*, :/]
operators.map do |op|
splits = string.split(op.to_s)
splits.map(&:to_f).inject(op) if splits.size > 1
end.compact.first
end
快乐的编码!