Update README.md
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
## Updata
|
||||
更新反三角函数的定义域判定,取整函数floor、ceil和round和阶乘运算的支持,同时更新变量暂存计算
|
||||
更新反三角函数的定义域判定,取整函数floor、ceil以及round和阶乘运算的支持,同时更新变量暂存计算
|
||||
|
||||
# 数据结构课设
|
||||
|
||||
|
||||
@@ -1,16 +1,35 @@
|
||||
#include "Calc.h"
|
||||
#include <iostream>
|
||||
#include<algorithm>
|
||||
|
||||
// <20><>̬<EFBFBD><CCAC>Ա<EFBFBD><D4B1>ʼ<EFBFBD><CABC>
|
||||
Tokenizer Calc::tokenizer;
|
||||
InfixToPostfix Calc::converter;
|
||||
PostfixEval Calc::evaluator;
|
||||
|
||||
std::unordered_map<std::string, double> Calc::vars = {
|
||||
{"PAI", 2 * std::asin(1)},
|
||||
{"pi", 3.14159265358979},
|
||||
{"e", std::exp(1)}
|
||||
};
|
||||
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿڣ<D3BF><DAA3><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD> -> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
double Calc::eval(const string& expression) {
|
||||
std::string varName, rightExpr;
|
||||
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> x = 3 + sin(2)
|
||||
if (is_assign(expression, varName, rightExpr)) {
|
||||
vector<Token> tokens = tokenizer.run(rightExpr);
|
||||
vector<Token> postfix = converter.run(tokens);
|
||||
double val = evaluator.run(postfix, vars);
|
||||
vars[varName] = val;
|
||||
return val;
|
||||
}
|
||||
|
||||
vector<Token> tokens = tokenizer.run(expression);
|
||||
vector<Token> postfix = converter.run(tokens);
|
||||
return evaluator.run(postfix);
|
||||
return evaluator.run(postfix,vars);
|
||||
}
|
||||
|
||||
// <20><>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD>ӿڣ<D3BF><DAA3><EFBFBD> try-catch <20><>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD> bool <20><>־
|
||||
@@ -42,3 +61,18 @@ void Calc::debug(const string& expr) {
|
||||
cerr << "[Debug Error] " << e.what() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool Calc::is_assign(const std::string& expr, std::string& varName, std::string& rightExpr) {
|
||||
size_t eqPos = expr.find('=');
|
||||
if (eqPos != std::string::npos) {
|
||||
varName = expr.substr(0, eqPos);
|
||||
rightExpr = expr.substr(eqPos + 1);
|
||||
// ȥ<><C8A5><EFBFBD>ո<EFBFBD>
|
||||
varName.erase(remove_if(varName.begin(), varName.end(), isspace), varName.end());
|
||||
rightExpr.erase(remove_if(rightExpr.begin(), rightExpr.end(), isspace), rightExpr.end());
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>Ϸ<EFBFBD><CFB7><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>
|
||||
return !varName.empty() && std::all_of(varName.begin(), varName.end(), ::isalpha);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,11 @@ private:
|
||||
static Tokenizer tokenizer;
|
||||
static InfixToPostfix converter;
|
||||
static PostfixEval evaluator;
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
static std::unordered_map<std::string, double> vars;
|
||||
//<2F><>ֵ<EFBFBD>жϺʹ<CFBA><CDB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
static bool is_assign(const std::string& expr, std::string& varName, std::string& rightExpr);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,15 +14,20 @@ vector<Token> InfixToPostfix::run(const vector<Token>& infix) {
|
||||
//<2F><><EFBFBD><EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD>ߣ<EFBFBD>
|
||||
opStack.push(token);
|
||||
else if (token.is_ope()) {
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><DFBB><EFBFBD>ͬ<EFBFBD>ҽ<EFBFBD><D2BD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
while (!opStack.empty() && opStack.top().is_ope() &&
|
||||
(precedence(opStack.top()) > precedence(token) ||
|
||||
(precedence(opStack.top()) == precedence(token) && associativity(token) == Associativity::Left))) {
|
||||
output.push_back(opStack.top());
|
||||
opStack.pop();
|
||||
if (token.value == "!")
|
||||
//<2F><><EFBFBD><D7BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>бȽ<D0B1>
|
||||
opStack.push(token);
|
||||
else {
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><DFBB><EFBFBD>ͬ<EFBFBD>ҽ<EFBFBD><D2BD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
while (!opStack.empty() && opStack.top().is_ope() &&
|
||||
(precedence(opStack.top()) > precedence(token) ||
|
||||
(precedence(opStack.top()) == precedence(token) && associativity(token) == Associativity::Left))) {
|
||||
output.push_back(opStack.top());
|
||||
opStack.pop();
|
||||
}
|
||||
//<2F><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ
|
||||
opStack.push(token);
|
||||
}
|
||||
//<2F><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ
|
||||
opStack.push(token);
|
||||
}
|
||||
else if (token.is_LP())
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>ջ
|
||||
|
||||
@@ -24,15 +24,25 @@ double PostfixEval::run(const std::vector<Token>& postfix, const unordered_map<s
|
||||
}
|
||||
else stk.push(it->second);
|
||||
}
|
||||
else if (token.is_ope()) {
|
||||
//ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>ж<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>
|
||||
if (stk.size() < 2) throw runtime_error("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
||||
double b = stk.top();
|
||||
stk.pop();
|
||||
double a = stk.top();
|
||||
stk.pop();
|
||||
double res = apply_BO(token.value, a, b);
|
||||
stk.push(res);
|
||||
else if (token.is_ope()) {
|
||||
if (token.value == "!") {
|
||||
if (stk.empty())
|
||||
throw runtime_error("<EFBFBD>׳˲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
||||
double x = stk.top(); stk.pop();
|
||||
stk.push(apply_Fac(x));
|
||||
}
|
||||
else {
|
||||
//ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>ж<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>
|
||||
if (stk.size() < 2)
|
||||
throw runtime_error("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
||||
double b = stk.top();
|
||||
stk.pop();
|
||||
double a = stk.top();
|
||||
stk.pop();
|
||||
double res = apply_BO(token.value, a, b);
|
||||
stk.push(res);
|
||||
}
|
||||
|
||||
}
|
||||
else if (token.is_fun()) {
|
||||
//ȡ<><C8A1>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>һԪ<D2BB><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱥ<EFBFBD><C8BA><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
|
||||
@@ -63,9 +73,16 @@ double PostfixEval::apply_BO(const string& op, double a, double b) {
|
||||
}
|
||||
if (op == "^") return pow(a, b);
|
||||
if (op == "%") {
|
||||
if (b == 0) throw runtime_error("ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>");
|
||||
if (b == 0)
|
||||
throw runtime_error("ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>");
|
||||
return std::fmod(a, b);
|
||||
}
|
||||
if (op == "//") {
|
||||
if (b == 0)
|
||||
throw runtime_error("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>");
|
||||
return std::floor(a / b); // <20><><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
|
||||
throw runtime_error("δ֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" + op);
|
||||
}
|
||||
|
||||
@@ -87,11 +104,41 @@ double PostfixEval::apply_UF(const string& func, double x) {
|
||||
throw runtime_error("log<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0");
|
||||
return log(x);
|
||||
}
|
||||
if (f == "ln") {
|
||||
if(x<=0)
|
||||
throw runtime_error("ln<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0");
|
||||
return log(x) / log(exp(1));
|
||||
}
|
||||
if (f == "exp") return exp(x);
|
||||
if (f == "abs") return fabs(x);
|
||||
if (f == "asin") return asin(x);
|
||||
if (f == "acos") return acos(x);
|
||||
if (f == "asin") {
|
||||
if (x < -1 || x > 1)
|
||||
throw runtime_error("asin <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> [-1, 1] <20><>Χ<EFBFBD><CEA7>");
|
||||
return std::asin(x);
|
||||
}
|
||||
if (f == "acos") {
|
||||
if (x < -1 || x > 1)
|
||||
throw runtime_error("asin <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> [-1, 1] <20><>Χ<EFBFBD><CEA7>");
|
||||
return std::acos(x);
|
||||
}
|
||||
if (f == "atan") return atan(x);
|
||||
|
||||
if (f == "floor") return std::floor(x); // <20><><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>
|
||||
if (f == "ceil") return std::ceil(x); // <20><><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>
|
||||
if (f == "round") return std::round(x); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
throw runtime_error("δ֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" + func);
|
||||
}
|
||||
|
||||
double PostfixEval::apply_Fac(double x) {
|
||||
if (x < 0)
|
||||
throw runtime_error("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׳<EFBFBD>");
|
||||
if (x != floor(x))
|
||||
throw runtime_error("<EFBFBD>׳˲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
||||
|
||||
int n = static_cast<int>(x);
|
||||
double result = 1;
|
||||
for (int i = 2; i <= n; ++i)
|
||||
result *= i;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ private:
|
||||
|
||||
//Ӧ<><D3A6><EFBFBD><EFBFBD>ҽԺ<D2BD><D4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱥ<EFBFBD><C8BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>sin, cos, log
|
||||
double apply_UF(const string& func, double x);
|
||||
|
||||
//Ӧ<><D3A6><EFBFBD><EFBFBD>һԪ<D2BB><D4AA><EFBFBD><D7BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C>磡
|
||||
double apply_Fac(double x);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,27 +5,29 @@
|
||||
using namespace std;
|
||||
|
||||
vector<Token> Tokenizer::run(const string& expr) {
|
||||
expression = expr;
|
||||
pos = 0;
|
||||
vector<Token> tokens;
|
||||
|
||||
expression = expr;
|
||||
pos = 0;
|
||||
vector<Token> tokens;
|
||||
|
||||
// <20><>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ʽ
|
||||
while (pos < expression.length()) {
|
||||
|
||||
skipWhitespace();// <20><><EFBFBD><EFBFBD><EFBFBD>հ<EFBFBD><D5B0>ַ<EFBFBD>
|
||||
if (pos >= expression.length()) break;
|
||||
|
||||
char current = expression[pos];
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>һԪ<D2BB><D4AA><EFBFBD>ſ<EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (is_dig(current) || (current == '-' && is_UMC(tokens)))
|
||||
if (is_dig(current) || (current == '-' && is_UMC(tokens)))
|
||||
tokens.push_back(readNumber());
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
else if (is_let(current))
|
||||
else if (is_let(current))
|
||||
tokens.push_back(readIdentifier());
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
else
|
||||
else
|
||||
tokens.push_back(readOperatorOrParen());
|
||||
}
|
||||
|
||||
@@ -69,13 +71,18 @@ Token Tokenizer::readIdentifier() {
|
||||
|
||||
//ʶ<><CAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
skipWhitespace();
|
||||
if (pos < expression.length() && expression[pos] == '(')
|
||||
if (pos < expression.length() && expression[pos] == '(')
|
||||
return Token(TokenType::Function, name);
|
||||
else
|
||||
else
|
||||
return Token(TokenType::Variable, name);
|
||||
}
|
||||
|
||||
Token Tokenizer::readOperatorOrParen() {
|
||||
if (expression[pos] == '/' && pos + 1 < expression.length() && expression[pos + 1] == '/') {
|
||||
pos += 2; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>
|
||||
return Token(TokenType::Operator, "//", 2, Associativity::Left);
|
||||
}
|
||||
|
||||
char c = expression[pos++]; // <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
|
||||
|
||||
// <20>ж<EFBFBD><D0B6>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>Ͳ<EFBFBD><CDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ Token
|
||||
@@ -84,7 +91,9 @@ Token Tokenizer::readOperatorOrParen() {
|
||||
case '-': return Token(TokenType::Operator, "-", 1, Associativity::Left);
|
||||
case '*': return Token(TokenType::Operator, "*", 2, Associativity::Left);
|
||||
case '/': return Token(TokenType::Operator, "/", 2, Associativity::Left);
|
||||
case '%': return Token(TokenType::Operator, "%", 2, Associativity::Left);
|
||||
case '^': return Token(TokenType::Operator, "^", 3, Associativity::Right);
|
||||
case '!': return Token(TokenType::Operator, "!", 4, Associativity::Right);
|
||||
case '(': return Token(TokenType::LeftParen, "(");
|
||||
case ')': return Token(TokenType::RightParen, ")");
|
||||
default:
|
||||
@@ -111,5 +120,5 @@ bool Tokenizer::is_let(char c) const {
|
||||
|
||||
bool Tokenizer::is_OpeCh(char c) const {
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>
|
||||
return c == '+' || c == '-' || c == '*' || c == '/' || c == '^';
|
||||
}
|
||||
return c == '+' || c == '-' || c == '*' || c == '/' || c == '^' || c == '%';
|
||||
}
|
||||
Reference in New Issue
Block a user