func evalArithmeticExp(s) { func evalExp(s) { func operate(s, op) { s.split(op).map{|c| Number(c) }.reduce(op) } func add(s) { operate(s.sub(/^\+/,'').sub(/\++/,'+'), '+') } func subtract(s) { s.gsub!(/(\+-|-\+)/,'-') if (s ~~ /--/) { return(add(s.sub(/--/,'+'))) } var b = s.split('-') b.len == 3 ? (-1*Number(b[1]) - Number(b[2])) : operate(s, '-') } s.gsub!(/[()]/,'').gsub!(/-\+/, '-') var reM = /\*/ var reMD = %r"(\d+\.?\d*\s*[*/]\s*[+-]?\d+\.?\d*)" var reA = /\d\+/ var reAS = /(-?\d+\.?\d*\s*[+-]\s*[+-]?\d+\.?\d*)/ while (var match = reMD.match(s)) { match[0] ~~ reM ? s.sub!(reMD, operate(match[0], '*').to_s) : s.sub!(reMD, operate(match[0], '/').to_s) } while (var match = reAS.match(s)) { match[0] ~~ reA ? s.sub!(reAS, add(match[0]).to_s) : s.sub!(reAS, subtract(match[0]).to_s) } return s } var rePara = /(\([^\(\)]*\))/ s.split!.join!('').sub!(/^\+/,'') while (var match = s.match(rePara)) { s.sub!(rePara, evalExp(match[0])) } return Number(evalExp(s)) }