前言
前言:本次使用VS2017 C++实现表达式的运算,支持阶乘,三角函数,反三角函数等函数,基本四则运算,乘法,取余数,取整等运算,另外还有计算平均数,方差,标准差等功能。
一、采用调度场算法直接运算
具体算法可以网上搜索,本次运算解决了前缀的正负运算,以及后缀的阶乘运算。多参数函数的运算以及嵌套,网上最多可扩展到单参数函数。由于采用了double类型,表达式精度可能会有影响,另外,表达式要完全准确,且要注意英文字母都要小写。
二、使用方法
1.函数介绍
函数说明如下:
函数或操作符 | 功能与说明 | 参数个数 | 使用示例 |
---|---|---|---|
pi | 常数π | ||
e | 常数e或10ⁿ | 如2500可写成2.5e3 | |
+ | 加法或正号 | ||
- | 减法或负号 | ||
* | 乘法 | ||
/ | 除法 | ||
^ | 乘方 | ||
% | 取余数 | ||
\ | 整除 | ||
! | 阶乘 | 如5! | |
sqr(x) | 求根号 | 1 | 如sqr(2) |
sin(x) | 求正弦 | 1 | |
cos(x) | 求余弦 | 1 | |
tan(x) | 求正切 | 1 | |
asin(x) | 求反正弦 | 1 | |
acos(x) | 求反余弦 | 1 | |
atan(x) | 求反正切 | 1 | |
sinh(x) | 求双曲正弦 | 1 | |
cosh(x) | 求双曲余弦 | 1 | |
tanh(x) | 求双曲正切 | 1 | |
asinh(x) | 求反双曲正弦 | 1 | |
acosh(x) | 求反双曲余弦 | 1 | |
atanh(x) | 求反双曲正切 | 1 | |
ln(x) | 求自然对数 | 1 | |
log(x) | 求以10为底的对数 | 1 | |
exp(x) | 求e的幂 | 1 | |
abs(x) | 求绝对值 | 1 | |
ceil(x) | 向下取整 | 1 | |
floor(x) | 向上取整 | 1 | |
int(x) | 取整 | 1 | |
round(x) | 四舍五入取整 | 1 | |
rad(x) | 度数转弧度 | 1 | |
deg(x) | 弧度转度数 | 1 | |
max(y,x) | 求两者的较大值 | 2 | 如max(1,2) |
min(y,x) | 求两者的较小值 | 2 | 如min(1,2) |
hypot(y,x) | 求直角三角形的斜边长 | 2 | 如hypot(3,4) |
atan2(y,x) | 求y/x的辐角 | 2 | 如atan2(3,4) |
avg(x1,x2,…) | 求平均数 | 不定 | 如avg(1,2)或avg(1,2,3) |
var(x1,x2,…) | 求方差 | 不定 | 如var(1,2)或var(1,2,3) |
stdev(x1,x2,…) | 求标准差 | 不定 | 如stdev(1,2)或stdev(1,2,3) |
2.完整代码
代码如下(示例):
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <limits>
#include <iomanip>
#define pi 3.14159265358979323846
#define ee 2.7182818284590452354
double Eval(char *ex, int *Err);
int main()
{
int Err1, s = 1;
double result;
char Input[999];
char d;
while (s) {
std::cout << "请输入算术表达式" << std::endl;
std::cin >> Input;
result = Eval(Input, &Err1);
if (Err1)
std::cout << "输出" << std::setprecision(15) << result << std::endl;
else
std::cout << "输入错误!" << std::endl;
sss:
std::cout << "是否继续:Y/N" << std::endl;
fflush(stdin);
std::cin >> d;
if (d == 'Y' || d == 'y')
system("cls");
else if (d == 'N' || d == 'n')
s = 0;
else {
system("cls");
goto sss;
}
}
return (0);
}
struct P_N {
double number;
P_N *next;
};
struct P_F {
char si;
P_F *next;
};
int scmp(char s1, char s2) {
switch (s1) {
case '+':
case '-':
if (s2 == '+' || s2 == '-' || s2 == ',' || s2 == ')' || s2 == '$')
return (1);
else
return (-1);
case '*':
case '/':
case '\\':
case '%':
case '^':
case '0':
case '1':
if (s2 == '+' || s2 == '-' || s2 == '*' || s2 == '/' || s2 == '%'
|| s2 == '\\' || s2 == ',' || s2 == ')' || s2 == '$')
return (1);
else
return (-1);
case '!':
if (s2 == '+' || s2 == '-' || s2 == '*' || s2 == '/' || s2 == '%'
|| s2 == '\\' || s2 == '^' || s2 == '!' || s2 == ',' || s2 == ')'
|| s2 == '$')
return (1);
else
return (2);
case '\0':
return (2);
case '$':
if (s2 == ',' || s2 == ')')
return (2);
else if (s2 == '$')
return (0);
else
return (-1);
case ',':
if (s2 == ')')
return (3);
else if (s2 == '$')
return (2);
else
return (-1);
case 'f':
case 'g':
case 'h':
case 'E':
case 'F':
case 'G':
case 'K':
if (s2 == ')')
return (0);
else if (s2 == '$')
return (2);
else
return (-1);
default:
if (s2 == ')')
return (0);
else if (s2 == ',' || s2 == '$')
return (2);
else
return (-1);
}
}
void cut(char **argmt, int n) {
*argmt = *argmt + n;
}
double lib(char **argmt, int *argtest) {
long double g;
char c;
char wa[3] = "\0";
int df = 0;
int dk = 0;
c = **argmt;
if (c == 'p') {
strncpy_s(wa, *argmt, 2);
if (strcmp(wa, "pi") == 0) {
cut(argmt, 2);
g = pi;
}
return (g);
}
if (c == 'e') {
cut(argmt, 1);
g = ee;
c = **argmt;
if ((c <= 57 && c >= 48) || c == '.')
*argtest = 0;
return (g);
}
if ((c > 57 || c < 48) && c != '.')
*argtest = 0;
g = atof(*argmt);
if (c == '.') {
cut(argmt, 1);
df = 1;
c = **argmt;
if (c == 'e' || c == 'E')
*argtest = 0;
}
while (c <= 57 && c >= 48) {
cut(argmt, 1);
c = **argmt;
if (dk == 0)
if (c == 'e' || c == 'E') {
dk = 1;
cut(argmt, 1);
c = **argmt;
if (c == '-' || c == '+') {
cut(argmt, 1);
c = **argmt;
if (c > 57 || c < 48)
*argtest = 0;
}
else if (c > 57 || c < 48)
*argtest = 0;
}
if (df == 0 && dk == 0)
if (c == '.') {
cut(argmt, 1);
df = 1;
c = **argmt;
if (c == 'e' || c == 'E') {
dk = 1;
cut(argmt, 1);
c = **argmt;
if (c == '-' || c == '+') {
cut(argmt, 1);
c = **argmt;
if (c > 57 || c < 48)
*argtest = 0;
}
else if (c > 57 || c < 48)
*argtest = 0;
}
}
if (df == 1 || dk == 1)
if (c == '.')
*argtest = 0;
if (dk == 1)
if (c == 'e' || c == 'E')
*argtest = 0;
}
return (g);
}
void push_f(P_F ** argflag, int *argp_f, int *argtes, char cf) {
P_F *p = new P_F;
(*argp_f)++;
p->si = cf;
p->next = *argflag;
*argflag = p;
*argtes = 1;
}
char pop_f(P_F ** argflag, int *argp_f, int *argtest) {
char c;
P_F *p = *argflag;
if (p != NULL) {
(*argp_f)--;
c = p->si;
*argflag = (*argflag)->next;
delete p;
return (c);
}
else {
*argtest = 0;
return ('\0');
}
}
void push_n(P_N ** argnum, int *argp_n, int *argtes, double cn) {
P_N *p = new P_N;
(*argp_n)++;
p->number = cn;
p->next = *argnum;
*argnum = p;
*argtes = 0;
}
double pop_n(P_N ** argnum, int *argp_n, int *argtest) {
double c;
P_N *p = *argnum;
if (p != NULL) {
(*argp_n)--;
c = p->number;
*argnum = (*argnum)->next;
delete p;
return (c);
}
else {
*argtest = 0;
return (0.0);
}
}
char fd(char dw, char **argmt) {
char wt[5] = "\0";
char wd[4] = "\0";
char wk[6] = "\0";
char wa[7] = "\0";
switch (dw) {
case 's':
strncpy_s(wt, *argmt, 4);
strncpy_s(wk, *argmt, 5);
strncpy_s(wa, *argmt, 6);
if (strcmp(wt, "sin(") == 0) {
cut(argmt, 4);
return ('s');
}
else if (strcmp(wt, "sqr(") == 0) {
cut(argmt, 4);
return ('q');
}
else if (strcmp(wk, "sinh(") == 0) {
cut(argmt, 5);
return ('a');
}
else if (strcmp(wa, "stdev(") == 0) {
cut(argmt, 6);
return ('G');
}
else {
return ('\0');
}
case 'c':
strncpy_s(wt, *argmt, 4);
strncpy_s(wk, *argmt, 5);
if (strcmp(wt, "cos(") == 0) {
cut(argmt, 4);
return ('c');
}
else if (strcmp(wk, "cosh(") == 0) {
cut(argmt, 5);
return ('b');
}
else if (strcmp(wk, "ceil(") == 0) {
cut(argmt, 5);
return ('H');
}
else {
return ('\0');
}
case 't':
strncpy_s(wt, *argmt, 4);
strncpy_s(wk, *argmt, 5);
if (strcmp(wt, "tan(") == 0) {
cut(argmt, 4);
return ('t');
}
else if (strcmp(wk, "tanh(") == 0) {
cut(argmt, 5);
return ('d');
}
else {
return ('\0');
}
case 'l':
strncpy_s(wd, *argmt, 3);
strncpy_s(wt, *argmt, 4);
if (strcmp(wd, "ln(") == 0) {
cut(argmt, 3);
return ('l');
}
else if (strcmp(wt, "log(") == 0) {
cut(argmt, 4);
return ('n');
}
else {
return ('\0');
}
case 'e':
strncpy_s(wt, *argmt, 4);
if (strcmp(wt, "exp(") == 0) {
cut(argmt, 4);
return ('e');
}
else {
return ('\0');
}
case 'm':
strncpy_s(wt, *argmt, 4);
if (strcmp(wt, "max(") == 0) {
cut(argmt, 4);
return ('f');
}
else if (strcmp(wt, "min(") == 0) {
cut(argmt, 4);
return ('g');
}
else {
return ('\0');
}
case 'h':
strncpy_s(wa, *argmt, 6);
if (strcmp(wa, "hypot(") == 0) {
cut(argmt, 6);
return ('h');
}
else {
return ('\0');
}
case 'v':
strncpy_s(wt, *argmt, 4);
if (strcmp(wt, "var(") == 0) {
cut(argmt, 4);
return ('F');
}
else {
return ('\0');
}
case 'f':
strncpy_s(wa, *argmt, 6);
if (strcmp(wa, "floor(") == 0) {
cut(argmt, 6);
return ('I');
}
else {
return ('\0');
}
case 'i':
strncpy_s(wt, *argmt, 4);
if (strcmp(wt, "int(") == 0) {
cut(argmt, 4);
return ('J');
}
else {
return ('\0');
}
case 'r':
strncpy_s(wt, *argmt, 4);
strncpy_s(wa, *argmt, 6);
if (strcmp(wt, "rad(") == 0) {
cut(argmt, 4);
return ('i');
}
else if (strcmp(wa, "round(") == 0) {
cut(argmt, 6);
return ('D');
}
else {
return ('\0');
}
case 'd':
strncpy_s(wt, *argmt, 4);
if (strcmp(wt, "deg(") == 0) {
cut(argmt, 4);
return ('j');
}
else {
return ('\0');
}
case 'a':
strncpy_s(wt, *argmt, 4);
strncpy_s(wk, *argmt, 5);
strncpy_s(wa, *argmt, 6);
if (strcmp(wt, "abs(") == 0) {
cut(argmt, 4);
return ('u');
}
else if (strcmp(wt, "avg(") == 0) {
cut(argmt, 4);
return ('E');
}
else if (strcmp(wk, "asin(") == 0) {
cut(argmt, 5);
return ('v');
}
else if (strcmp(wk, "acos(") == 0) {
cut(argmt, 5);
return ('w');
}
else if (strcmp(wk, "atan(") == 0) {
cut(argmt, 5);
return ('x');
}
else if (strcmp(wa, "asinh(") == 0) {
cut(argmt, 6);
return ('A');
}
else if (strcmp(wa, "acosh(") == 0) {
cut(argmt, 6);
return ('B');
}
else if (strcmp(wa, "atanh(") == 0) {
cut(argmt, 6);
return ('C');
}
else if (strcmp(wa, "atan2(") == 0) {
cut(argmt, 6);
return ('K');
}
else {
return ('\0');
}
default:
return ('\0');
}
}
char getn(char **argmt, int *argtrs, double *argnu, int *argtest, int *argtes) {
char c;
char sj;
c = **argmt;
*argnu = 0.0;
*argtrs = 0;
if (c == '*' || c == '/' || c == '(' || c == ')' || c == '^'
|| c == '%' || c == '!' || c == '\\' || c == ',' || c == '$') {
if (c == '(')
if (*argtes == 0)
*argtest = 0;
if (c == '!')
if (*argtes == 1)
*argtest = 0;
*argtrs = 1;
cut(argmt, 1);
return (c);
}
else if (c == '+' && *argtes) {
*argtrs = 1;
cut(argmt, 1);
return ('0');
}
else if (c == '-' && *argtes) {
*argtrs = 1;
cut(argmt, 1);
return ('1');
}
else if (c == '+' || c == '-') {
*argtrs = 1;
cut(argmt, 1);
return (c);
}
else {
sj = fd(c, argmt);
if (sj != '\0') {
if (*argtes == 0)
*argtest = 0;
*argtrs = 1;
return (sj);
}
*argnu = lib(argmt, argtest);
return ('\0');
}
}
double max(double a, double b) {
return fmax(a, b);
}
double min(double a, double b) {
return fmin(a, b);
}
double avg(double *an, int l) {
double tmp = 0;
int i;
for (i = 0; i < l; i++)
tmp += *(an + i);
return (tmp / l);
}
double var(double *an, int l) {
double tmp = 0;
double tmp2 = 0;
int i;
tmp2 = avg(an, l);
for (i = 0; i < l; i++)
tmp += (*(an + i) - tmp2) * (*(an + i) - tmp2);
return (tmp / l);
}
double stdev(double *an, int l) {
return (sqrt(var(an, l)));
}
double fint(double x) {
if (x == x) {
if (x >= 0)
return (floor(x));
else
return (ceil(x));
}
else
return (x);
}
double op(char mk, double dd) {
switch (mk) {
case 'A':
return (asinh(dd));
case 'B':
return (acosh(dd));
case 'C':
return (atanh(dd));
case 'D':
return (round(dd));
case 'a':
return (sinh(dd));
case 'b':
return (cosh(dd));
case 'd':
return (tanh(dd));
case 'e':
return (exp(dd));
case 'i':
return (dd / 180 * pi);
case 'j':
return (dd / pi * 180);
case 's':
return (sin(dd));
case 'c':
return (cos(dd));
case 't':
return (tan(dd));
case 'q':
return (sqrt(dd));
case 'l':
return (log(dd));
case 'n':
return (log10(dd));
case 'u':
return (fabs(dd));
case 'v':
return (asin(dd));
case 'w':
return (acos(dd));
case 'x':
return (atan(dd));
case '!':
return (tgamma(dd + 1));
case '1':
return (-dd);
case 'H':
return (ceil(dd));
case 'I':
return (floor(dd));
case 'J':
return (fint(dd));
default:
return (dd);
}
}
double fop(char mk, P_N ** argnum, int *argp_n, int mpa, int *argtest) {
double a;
double b;
double *an;
double ret;
int i;
switch (mk) {
case 'f':
{
if (mpa == 1) {
a = pop_n(argnum, argp_n, argtest);
b = pop_n(argnum, argp_n, argtest);
return (max(b, a));
}
else {
*argtest = 0;
return (0);
}
}
case 'g':
{
if (mpa == 1) {
a = pop_n(argnum, argp_n, argtest);
b = pop_n(argnum, argp_n, argtest);
return (min(b, a));
}
else {
*argtest = 0;
return (0);
}
}
case 'h':
{
if (mpa == 1) {
a = pop_n(argnum, argp_n, argtest);
b = pop_n(argnum, argp_n, argtest);
return (hypot(b, a));
}
else {
*argtest = 0;
return (0);
}
case 'K':
{
if (mpa == 1) {
a = pop_n(argnum, argp_n, argtest);
b = pop_n(argnum, argp_n, argtest);
return (atan2(b, a));
}
else {
*argtest = 0;
return (0);
}
}
case 'E':
{
an = new double[mpa + 1];
for (i = 0; i < mpa + 1; i++)
*(an + mpa - i) = pop_n(argnum, argp_n, argtest);
ret = avg(an, mpa + 1);
delete an;
return (ret);
}
case 'F':
{
an = new double[mpa + 1];
for (i = 0; i < mpa + 1; i++)
*(an + mpa - i) = pop_n(argnum, argp_n, argtest);
ret = var(an, mpa + 1);
delete an;
return (ret);
}
case 'G':
{
an = new double[mpa + 1];
for (i = 0; i < mpa + 1; i++)
*(an + mpa - i) = pop_n(argnum, argp_n, argtest);
ret = stdev(an, mpa + 1);
delete an;
return (ret);
}
}
default:
*argtest = 0;
return (0);
}
}
double zhi(double d1, double d2, char v) {
switch (v) {
case '+':
return (d1 + d2);
case '-':
return (d1 - d2);
case '*':
return (d1 * d2);
case '/':
return (d1 / d2);
case '%':
return fmod(d1, d2);
case '\\':
return fint(d1 / d2);
default:
return (pow(d1, d2));
}
}
double Eval(char *ex, int *Err) {
char *mt = NULL;
int p_n = -1;
int p_f = -1;
P_N *num = NULL;
P_F *flag = NULL;
int tes = 1;
double nu = 0.0;
int trs = 0;
int test = 1;
int length = strlen(ex);
char *exi = new char[length + 10];
char sym;
double a, b, retnum;
int i, j;
int mpa = 0;
char sy;
for (i = 0; i < length; i++) {
exi[i] = *(ex + i);
if (exi[i] == '$')
test = 0;
}
exi[i] = '$';
exi[i + 1] = '\0';
mt = exi;
push_f(&flag, &p_f, &tes, '$');
sym = getn(&mt, &trs, &nu, &test, &tes);
while ((sym != '$' || flag->si != '$') && test) {
if (trs == 0) {
if (tes == 0)
test = 0;
push_n(&num, &p_n, &tes, nu);
sym = getn(&mt, &trs, &nu, &test, &tes);
}
else {
j = scmp(flag->si, sym);
if (j == -1) {
push_f(&flag, &p_f, &tes, sym);
if (sym == '!')
tes = 0;
sym = getn(&mt, &trs, &nu, &test, &tes);
}
else if (j == 0) {
if (flag->si == 'f' || flag->si == 'g' || flag->si == 'h'
|| flag->si == 'E' || flag->si == 'F' || flag->si == 'G'
|| flag->si == 'K') {
sy = pop_f(&flag, &p_f, &test);
push_n(&num, &p_n, &tes, fop(sy, &num, &p_n, mpa, &test));
mpa = 0;
}
else {
sy = pop_f(&flag, &p_f, &test);
a = pop_n(&num, &p_n, &test);
push_n(&num, &p_n, &tes, op(sy, a));
}
sym = getn(&mt, &trs, &nu, &test, &tes);
}
else if (j == 1)
if (flag->si == '0' || flag->si == '1' || flag->si == '!') {
a = pop_n(&num, &p_n, &test);
sy = pop_f(&flag, &p_f, &test);
push_n(&num, &p_n, &tes, op(sy, a));
}
else {
a = pop_n(&num, &p_n, &test);
b = pop_n(&num, &p_n, &test);
sy = pop_f(&flag, &p_f, &test);
push_n(&num, &p_n, &tes, zhi(b, a, sy));
}
else if (j == 3) {
mpa++;
pop_f(&flag, &p_f, &test);
}
else
test = 0;
}
}
if (p_n == 0 && test == 1)
retnum = num->number;
else {
test = 0;
retnum = 0.0;
}
*Err = test;
delete exi;
while (p_f >= 0)
pop_f(&flag, &p_f, &test);
while (p_n >= 0)
pop_n(&num, &p_n, &test);
return (retnum);
}
总结
本次实现了使用C++完成对表达式的计算,是否有其他的问题可以说明,由于是四五年前写的代码,所以没有什么注释,也写的比较混乱。