Ruby
Number of characters: 170
Obfuscated:
def s(x)
while x.sub!(/\(([^\(\)]*?)\)/){s($1)}
x.gsub!('--','')
end
while x.sub!(/(-?[\d.]+)[ ]*([+\-*\/])[ ]*(-?[\d.]+)/){$1.to_f.send($2,$3.to_f)}
end
x.strip.to_f
end
Readable:
def s(x)
while x.sub!(/\(([^\(\)]*?)\)/){s($1)}
x.gsub!('--','')
end
while x.sub!(/(-?[\d.]+)[ ]*([+\-*\/])[ ]*(-?[\d.]+)/){$1.to_f.send($2,$3.to_f)}
end
x.strip.to_f
end
[
['1 + 3 / -8', -0.5],
['2*3*4*5+99', 219],
['4 * (9 - 4) / (2 * 6 - 2) + 8', 10],
['1 + ((123 * 3 - 69) / 100)', 4],
['2.45/8.5*9.27+(5*0.0023)',2.68344117647059],
['(3+7) - (5+2)', 3]
].each do |pair|
a,b = s(String.new(pair[0])),pair[1]
print pair[0].ljust(25), ' = ', b, ' (', a==b, ')'
puts
end
There is no real obfuscation to this one, which I decided to post fresh since it's wildly different from my first. I should have seen this from the start. The process is a very simple process of elimination: find and resolve the highest pair of parenthesis (the most nested) into a number until no more are found, then resolve all the existing numbers and operations into the result. And, while resolving parenthetical statements I have it strip all double-dashes (Float.to_f doesn't know what to do with them).
So, it supports positive and negative numbers (+3, 3, & -3) and even negated sub-expressions within the parenthesis just by the order of processing. The only shorter implementation is the Perl (w/o eval) one.
Edit: I'm still chasing Perl, but this is the second smallest answer right now. I shrunk it with changes to the second regex and by changing the treatment of the string to be destructive (replaces the old string). This eliminated the need to duplicate the string, which I found out to just be a new pointer to the string. And renaming the function to s from solve saved a few characters.