c/c++及java语言有没有科学计算器的库
c/c++语言及java语言有没有科学计算器的库?
比如,这个库提供这样的函数
double cal(const char * s);
调用者这样调用即可(只考虑实数范围),
char buf [] = "2 * ( 3+5-6*( log(5,log(2,3)) - pow(2.5,6.3) )/sqrtex(25.5,3.2) )" ;
double result =cal(buf);
函数输入一个合法的字符串,返回一个这个字符所代表的计算式的近似值,字符串中:
1) log(5,log(2,3)) 底不是10,所以可以用 c 语言的logx/logy来换底,而且还要递归计算。
2) pow(2.5,6.3) 在计算机小数次方。
3) sqrtex(25.5,3.2) 在开小数次方,可用c语言的 pow()来封装。
对于字符串的解析,可能有好多种方法,其实还是比较麻烦的。
查了一下,GSL是一个gnu的科学计算库,但是好像不提供直接解析字符串式的。
如果没有我自己想写一个通用可扩展开源库,提供给c/c++/java来调用,甚至python等(python的eval()只能计算基本的),
初步想了一下,基本上可行, step如下:
1> 定义若干个包装函数,如sqrtex(a,b),log(x,y)等。
2> 用逆波兰式对字符串解析,并建立对应的二叉树。
3> 对二叉树进行遍历计算出结果。
如果没有成熟的开源库,有没有朋友想一起搞个实现?
[解决办法]
#include <iostream>#include <string>#include <map>#include <cmath>#include <cstdio>#include <cstdlib>#include <cctype>using namespace std;enum Token_value{ NAME, NUMBER, END, PLUS = '+', MINUS = '-', MODE='%',MUL = '*', DIV = '/', PRINT = ';', ASSIGN = '=', LP = '(', RP = ')', OR='|',XOR='^',AND='&',NOT='!',COMPL='~', SIN,COS,TAN,TANH,SINH,COSH,LN,LOG,POW,EXIT,};// 优先级 */% > +- > & > ^ > | =;Token_value curr_tok = PRINT;map<string, double> table;map<string,Token_value> operator_tokens;double term(bool get);double prim(bool get);Token_value get_token();int no_of_errors;/*!expr= term_or | term_or; term_or;term_or= term_xor ^ term_xor; term_xor;term_xor=term_and & term_and; term_and;term_and=term+term; term-term; term;term=prim*prim; prim/prim; prim%prim; prim pow prim; prim;prim= name ; number ;token;(unary)prim; (expr);*/double term_or(bool get);double term_xor(bool get);double term_and(bool get);double error(const string& s){ no_of_errors++; cerr << "error: " << s << "\n"; return 1;}double expr(bool get){ double left = term_or(get); for(;;) { switch(curr_tok) { case OR: left=(int)left | (int)term_or(true); break; default: return left; } }}double term_or(bool get){ double left=term_xor(get); for(;;) { switch(curr_tok) { case XOR: left=(int)left^(int)term_xor(true); default:return left; } }}double term_xor(bool get){ double left=term_and(get); for(;;) { switch(curr_tok) { case AND: left=(int)left&(int)term_and(true); default:return left; } }}double term_and(bool get){ double left = term(get); for(;;) { switch(curr_tok) { case PLUS: left += term(true); break; case MINUS: left -= term(true); break; default: return left; } }}/*double expr(bool get){ double left = term(get); for(;;) { switch(curr_tok) { case PLUS: left += term(true); break; case MINUS: left -= term(true); break; default: return left; } }}*/double term_profix(bool);double term_profix(bool get){ double left = prim(get); for(;;) { switch(curr_tok) { case NOT: { int sum = 1; int b=left>=0?1:-1; for(int i = 1; i<= (int)left; i++) sum*=i; return b* sum; } default: return left; } }}#define prim(a) term_profix(a)double term(bool get){ double left = prim(get); for(;;) { switch(curr_tok) { case MUL: left *= prim(true); break; case DIV: if(double d = prim(true)) { left /= d; break; } return error("divide by 0"); case MODE: left=(int)left % (int)(prim(true)); break; case POW: left = pow(left,prim(true)); break; default: return left; } } return left;}#undef primdouble number_value;string string_value;double prim(bool get)// ture get_token; false{ if(get) get_token(); switch(curr_tok) { case NUMBER: { double v = number_value; get_token(); return v; } case NAME: { double &v = table[string_value]; if(get_token() == ASSIGN) v = expr(true); return v; } case MINUS: return -prim(true); case SIN: return sin(prim(true)); case SINH: return asin(prim(true)); case COS: return cos(prim(true)); case COSH: return cosh(prim(true)); case TAN: return tan(prim(true)); case TANH: return atan(prim(true)); case LN: return log(prim(true)); case LOG: return log10(prim(true)); case NOT:return !prim(true); case COMPL:return ~(int)prim(true); case LP: { double e = expr(true); if(curr_tok != RP) return error(") expected"); get_token(); return e; } default: return error("primary expectd"); }}Token_value get_token(){ char ch; do { if(!cin.get(ch)) return curr_tok = END; } while(ch != '\n' && isspace(ch));// 跳过空格。 switch(ch) { case ';': case '\n': return curr_tok = PRINT;//如果是 ; \n,则返回。 case '*': case '/': case '+': case '-': case '%': case '(': case ')': case '=': case '&': case '|': case '^': case '~': case '!': return curr_tok = Token_value(ch);// token case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': cin.putback(ch); cin >> number_value; return curr_tok = NUMBER;// 当前符号为 NUMBER, 输入 number_value; default: if(isalpha(ch)) { string_value = ch; while(cin.get(ch) && isalnum(ch)|| ch=='_') string_value.push_back(ch); cin.putback(ch); for(int i = 0 ; i != string_value.size(); ++i) string_value[i] = tolower(string_value[i]); if(operator_tokens.find(string_value)!=operator_tokens.end()) { curr_tok=operator_tokens[string_value]; if(curr_tok == EXIT) exit(0); return curr_tok; } return curr_tok = NAME; } error("bad token"); return curr_tok = PRINT; }}void init(){ table["pi"] = 3.1415926535897932385; table["e"] = 2.718281828459; operator_tokens["sin"]=SIN; operator_tokens["sinh"]=SINH; operator_tokens["tan"]=TAN; operator_tokens["tanh"]=TANH; operator_tokens["cos"]=COS; operator_tokens["cosh"]=COSH; operator_tokens["lg"]=LOG; operator_tokens["ln"]=LN; operator_tokens["and"]=AND; operator_tokens["or"]=OR; operator_tokens["xor"]=XOR; operator_tokens["pow"]=POW; operator_tokens["exit"]=EXIT; // operator_tokens["EXIT"]=EXIT;}int main(){ init(); while(cin) { get_token(); if(curr_tok == END) break; if(curr_tok == PRINT) continue; cout<<"\t:="<< expr(false) << '\n'; } return no_of_errors;}