这两天写了一个符号求导的程序,没有任何化简,代码质量比较差。以后可以考虑把每个项coefficient * x^index单独提出来,把coefficient和index单独作为未知数x的属性。
该程序目前只支持多项式求导。
#include<bits/stdc++.h>
using namespace std;
const static int bign = 10033;
enum tokenType
{
Openbracket = 1, CloseBracket, Variable, ConstVar, OpType
};
typedef pair<int, string> token;
typedef vector<token> tokenlist;
int mapbracket[bign];
int bstack[bign];
int mtop;
inline int getType(char c)
{
if (c == '(')
{
return 1;
}
else if (c == ')')
{
return 2;
}
else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
{
return 3;
}
else if (c >= '0' && c <= '9')
{
return 4;
}
else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '^')
{
return 5;
}
else if (c == ' ' || c == '\n' || c == ';')
{
return 6;
}
}
void LexErrorOccur()
{
printf("Lexical Error\n");
}
inline int matoi(string &numstr)
{
int ret = 0;
for (int i = 0; i < numstr.length(); i++)
{
ret = ret * 10 + numstr[i] - '0';
}
return ret;
}
inline string tokenToString(tokenlist u,int n1)
{
string ret = "";
for (int i = 0; i < n1; i++)
{
ret += u[i].second;
}
return ret;
}
void LexAnalysis(string& Expr, tokenlist& tlist)
{
string lasttoken = "";
int lasttype = 0;
for (char c : Expr)
{
int typec = getType(c);
if (typec == 1 || typec == 2 || typec == 5 || typec == 6)
{
if (lasttype > 0)
{
tlist.push_back(make_pair(lasttype, lasttoken));
lasttype = 0;
lasttoken = "";
}
}
if (typec == 1 || typec == 2)
{
lasttype = typec;
lasttoken.push_back(c);
tlist.push_back(make_pair(lasttype, lasttoken));
lasttype = 0;
lasttoken = "";
}
else
{
if (typec == 4)
{
if (lasttype != 3)
{
lasttype = 4;
}
lasttoken.push_back(c);
}
else if (typec == 3)
{
if (lasttype == 4)
LexErrorOccur();
lasttype = 3;
lasttoken.push_back(c);
}
else if (typec == 5)
{
lasttype = 5;
lasttoken.push_back(c);
tlist.push_back(make_pair(lasttype, lasttoken));
lasttype = 0;
lasttoken = "";
}
}
}
if (lasttype != 0)
{
tlist.push_back(make_pair(lasttype, lasttoken));
}
}
bool testzero(token &u)
{
if (u.first == tokenType::ConstVar && u.second == "0")
{
return true;
}
return false;
}
int mDerivative(tokenlist& Expr, int b1, int e1, tokenlist& res, int resb)
{
assert(b1 >= 0 && b1 <= e1 && e1 <= Expr.size());
if (b1 == e1)
return resb;
//vector<pair<int, string> > ret;
//ret.push_back(make_pair(0, "+"));
if (e1 - b1 >= 2 && Expr[b1].first == tokenType::Openbracket && Expr[e1 - 1].first == tokenType::CloseBracket && mapbracket[e1 - 1] == b1)
{
return mDerivative(Expr, b1 + 1, e1 - 1, res, resb);
}
int inbracket = 0;
for (int i = b1; i < e1; i++)
{
if (Expr[i].first == tokenType::OpType)
{
char opchar = Expr[i].second[0];
if ((opchar == '+' || opchar == '-') && inbracket == 0)
{
resb = mDerivative(Expr, b1, i, res, resb);
res[resb++] = make_pair(tokenType::OpType, Expr[i].second);//derivative + & - rule
resb = mDerivative(Expr, i + 1, e1, res, resb);
return resb;
}
}
else if (Expr[i].first == tokenType::Openbracket)
{
inbracket++;
}
else if (Expr[i].first == tokenType::CloseBracket)
{
inbracket--;
}
}
for (int i = e1 - 1; i >= b1; i--)
{
if (Expr[i].first == tokenType::OpType)
{
char opchar = Expr[i].second[0];
if (opchar == '*' && inbracket == 0) // derivative * rule
{
res[resb++] = make_pair(tokenType::Openbracket, "(");
resb = mDerivative(Expr, b1, i, res, resb);
res[resb++] = make_pair(tokenType::CloseBracket, ")");
res[resb++] = make_pair(tokenType::OpType, "*");
res[resb++] = make_pair(tokenType::Openbracket, "(");
for (int j = i + 1; j < e1; j++)
{
res[resb++] = Expr[j];
}
res[resb++] = make_pair(tokenType::CloseBracket, ")");
res[resb++] = make_pair(tokenType::OpType, "+");
res[resb++] = make_pair(tokenType::Openbracket, "(");
for (int j = b1; j < i; j++)
{
res[resb++] = Expr[j];
}
res[resb++] = make_pair(tokenType::CloseBracket, ")");
res[resb++] = make_pair(tokenType::OpType, "*");
res[resb++] = make_pair(tokenType::Openbracket, "(");
resb = mDerivative(Expr, i + 1, e1, res, resb);
res[resb++] = make_pair(tokenType::CloseBracket, ")");
return resb;
}
if (opchar == '/' && inbracket == 0) //derivative / rule
{
res[resb++] = make_pair(tokenType::Openbracket, "(");
res[resb++] = make_pair(tokenType::Openbracket, "(");
resb = mDerivative(Expr, b1, i, res, resb);
res[resb++] = make_pair(tokenType::CloseBracket, ")");
res[resb++] = make_pair(tokenType::OpType, "*");
res[resb++] = make_pair(tokenType::Openbracket, "(");
for (int j = i + 1; j < e1; j++)
{
res[resb++] = Expr[j];
}
res[resb++] = make_pair(tokenType::CloseBracket, ")");
res[resb++] = make_pair(tokenType::OpType, "-");
res[resb++] = make_pair(tokenType::Openbracket, "(");
for (int j = b1; j < i; j++)
{
res[resb++] = Expr[j];
}
res[resb++] = make_pair(tokenType::CloseBracket, ")");
res[resb++] = make_pair(tokenType::OpType, "*");
res[resb++] = make_pair(tokenType::Openbracket, "(");
resb = mDerivative(Expr, i + 1, e1, res, resb);
res[resb++] = make_pair(tokenType::CloseBracket, ")");
res[resb++] = make_pair(tokenType::CloseBracket, ")");
res[resb++] = make_pair(tokenType::OpType, "/");
res[resb++] = make_pair(tokenType::Openbracket, "(");
for (int j = i + 1; j < e1; j++)
{
res[resb++] = Expr[j];
}
res[resb++] = make_pair(tokenType::CloseBracket, ")");
res[resb++] = make_pair(tokenType::OpType, "^");
res[resb++] = make_pair(tokenType::ConstVar, "2");
return resb;
}
}
else if (Expr[i].first == tokenType::Openbracket)
{
inbracket++;
}
else if (Expr[i].first == tokenType::CloseBracket)
{
inbracket--;
}
}
if (Expr[b1].first == tokenType::Variable)
{
if (e1 - b1 >= 3)
{
int indexn = matoi(Expr[e1 - 1].second);
res[resb++] = make_pair(tokenType::ConstVar, to_string(indexn));
res[resb++] = make_pair(tokenType::OpType, "*");
res[resb++] = make_pair(tokenType::Variable, Expr[b1].second);
res[resb++] = make_pair(tokenType::OpType, "^");
res[resb++] = make_pair(tokenType::ConstVar, to_string(indexn - 1));
}
else
{
res[resb++] = make_pair(tokenType::ConstVar, "1");
}
}
else
{
res[resb++] = make_pair(tokenType::ConstVar, "0");
}
return resb;
}
void solve()
{
string Expr = "(x^3 + 2 * x^2 + 19 * x)/(x^2 + x)";
tokenlist tlist, res(bign);
LexAnalysis(Expr, tlist);
int tn = tlist.size();
memset(mapbracket, -1, tn * sizeof(int));
for (int i = 0; i < tn; i++)
{
if (tlist[i].first == 1)
bstack[mtop++] = i;
if (tlist[i].first == 2)
{
assert(mtop > 0);
mapbracket[i] = bstack[--mtop];
}
}
assert(mtop == 0);
int ressize = mDerivative(tlist, 0, tlist.size(), res, 0);
string restr = tokenToString(res, ressize);
cout << restr << endl;
}
int main()
{
solve();
}