C (249 characters)
char*c;double m(char*s,int o){int i;c=s;double x=*s-40?strtod(c,&s):m(c+1,0);double y;for(;*c&&c-41;c++){for(i=0;i<7&&*c-"``-+/*^"[i];i++);if(i<7){if(i/2<=o/2){c-=*c!=41;break;}y=m(c+1,i);x=i-6?i-5?i-4?i-3?i-2?x:x-y:x+y:x/y:x*y:pow(x,y);}}return x;}
This is a somewhat-revamped version of my previous version. By using strtod instead of atof (props to P Daddy) I was able to cut it by ~90 chars!
Features
- Supports exponentation, multiplication, division, addition, and subtraction. Note that it DOES NOT support unary minus, since that wasn't mentioned in the spec, even though it was used in the OP's test cases. I thought it was ambiguous enough to leave out
- It's 249 chars long
- Supports double-precision arithmetic
- It's 249 chars long
- Supports PEMDAS, though exponentation associates as "x^y^z"->"(x^y)^z", not as "x^(y^z)"
- Assumes that input isn't garbage. Garbage in, garbage out.
- Did I mention it's 249 chars long? :P
Usage
Pass a pointer to a null-terminated array of chars, then 0. Like so:
m(charPtr,0)
You must include math.h and stdlib.h in the source file you call the function from. Also note that char*c is defined globally at the start of the code. So don't define any variable named c in anything using this. If you must have a way to negate things, "-[insert expression here]" is equivalent to "(0-[insert expression here])" the way the OP has precedence ordered