// C++ implementation of Derivative Arithmetic (Problem D ACM SP 1999) // #include #include #include #include #include using namespace std; class DA { float a, b; public: DA() { a = 0; b = 0; } DA(float aIn, float bIn) { a = aIn; b = bIn; } static DA add(const DA &X, const DA &Y) { return DA(X.a + Y.a, X.b + Y.b); } static DA subtract(const DA &X, const DA &Y) { return DA(X.a - Y.a, X.b - Y.b); } static DA times(const DA &X, const DA &Y) { return DA(X.a * Y.a, X.b * Y.a + X.a * Y.b); } static DA divide(const DA &X, const DA &Y) { if (X.a == 0 && Y.a == 0) { assert(Y.b); return DA(X.b / Y.b, 0.0 ); } if (Y.a == 0) { assert(false); return /* undefined */ DA(0,0);} return DA(X.a/Y.a, (X.b * Y.a - X.a * Y.b) / (Y.a*Y.a)); } static DA pow(const DA &X, int n) { if (X.a == 0.0 && n < 1) return /* undefined */ DA(0,0); float p = ::pow(X.a,n-1); return DA(p*X.a, n * X.b * p); } static DA sqrt(const DA &X) { if (X.a == 0 && X.b == 0) return DA(0,0); //if (X.a == 0) return /* undefined */ DA(0,0); if (X.a > 0) return DA(::sqrt(X.a), X.b /(2 * ::sqrt(X.a))); assert(false); return /* undefined */ DA(0,0); } static DA exp(const DA &X) { return DA(::exp(X.a), X.b * ::exp(X.a)); } static DA ln(const DA &X) { if (X.a > 0) return DA(::log(X.a), X.b/X.a); else assert(false); return /* undefined */ DA(0,0); } friend ostream& operator<<(ostream& o, const DA &X); friend istream& operator>>(istream& i, DA &X); }; inline const char* my(float x) { return x == int(x) ? ".0" : ""; } // ostream& operator<<(ostream& o, const DA &X) { return o << '(' << X.a << my(X.a) << ',' << X.b << my(X.b) << ')' << endl; } //{ return o << '(' << X.a << ',' << X.b << ')' << endl; } istream& operator>>(istream& i, DA &X) { char c; // i >> c; assert(c == '('); -- Hacked, parenth already seen! float a,b; i >> a; X.a = a; i >> c; assert(c == ','); i >> b; X.b = b; i >> c; assert(c == ')'); return i; } int main() { vector reg(10); stack S; char c; int n; DA Op1, Op2, Tmp; while (true) { cin >> c; switch (c) { case '(': cin >> Op1; S.push(Op1); break; case 'G': cin >> n; assert(n >= 0 && n < 10); S.push(reg[n]); break; case '+': Op2 = S.top(); S.pop(); Op1 = S.top(); S.pop(); Tmp = DA::add(Op1,Op2); S.push(Tmp); break; case '-': Op2 = S.top(); S.pop(); Op1 = S.top(); S.pop(); Tmp = DA::subtract(Op1,Op2); S.push(Tmp); break; case '*': Op2 = S.top(); S.pop(); Op1 = S.top(); S.pop(); Tmp = DA::times(Op1,Op2); S.push(Tmp); break; case '/': Op2 = S.top(); S.pop(); Op1 = S.top(); S.pop(); Tmp = DA::divide(Op1,Op2); S.push(Tmp); break; case '^': cin >> n; assert(n >= 0); Op1 = S.top(); S.pop(); Tmp = DA::pow(Op1,n); S.push(Tmp); break; case 'S': Op1 = S.top(); S.pop(); Tmp = DA::sqrt(Op1); S.push(Tmp); break; case 'E': Op1 = S.top(); S.pop(); Tmp = DA::exp(Op1); S.push(Tmp); break; case 'L': Op1 = S.top(); S.pop(); Tmp = DA::ln(Op1); S.push(Tmp); break; case 'P': cin >> n; assert(n >= 0 && n < 10); reg[n] = S.top(); S.pop(); break; case 'W': Op1 = S.top(); S.pop(); cout << Op1; break; case 'D': Op1 = S.top(); S.push(Op1); break; case 'Q': return 1; case ' ': case '\t': case '\n': break; default: assert(false); } //switch } // while }