首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

c/c++及java语言有没有科学计算器的库解决方案

2012-09-09 
c/c++及java语言有没有科学计算器的库c/c++语言及java语言有没有科学计算器的库?比如,这个库提供这样的函

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> 对二叉树进行遍历计算出结果。


如果没有成熟的开源库,有没有朋友想一起搞个实现?






[解决办法]

C/C++ code
#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;} 

热点排行