игрыстатьиматематические программырусский языкразноеоб авторе

Парсер выражений

en
java парсер
c++ парсер
javascript парсер
скачать исходный код
история версий

Парсер выражений - это разборщик строк типа sin(pi/4) реализованный на java, c++ и javascript. На основе парсера созданы проекты на java, которые можно скачать или запускать online - это научный калькулятор и построитель графиков

Список поддерживаемых функций и констант

Общие функции

exp(x) = ex - экспонента
log(x) - натуральный логарифм
pow(x, y) = xy - возведение в степень
sqrt(x) - корень квадратный
abs(x) = |x| - модуль
random() - случайное число между 0 и 1
min(x1, x2) - минимум
max(x1, x2) - максимум

Константы

pi = 3.141592653589793
e = 2.718281828459045
sqrt2 = sqrt(2) = 1.4142135623730951
sqrt1_2 = sqrt(1/2) = 0.7071067811865476
ln2 = loge(2) = log(2) = 0.6931471805599453
ln10 = loge(10) = log(10) = 2.302585092994046
log2e = log2(e) = 1/log(2) = 1.4426950408889634
log10e = log10(e) = 1/log(10) = 0.4342944819032518

Тригонометрические функции

sin(x) - синус
asin(x) - арксинус
cos(x) - косинус
acos(x) - арккосинус
tan(x) - тангенс
atan(x) - арктангенс
atan2(x,y) - арктангенс отношения x/y
cot(x)=cos(x)/sin(x) - котангенс
acot(x)=pi/2-atan(x) - арккотангенс
sec(x)=1/cos(x) - секанс
asec(x)=acos(1/x) - арксеканс
csc(x)=1/sin(x) - косеканс
acsc(x)=asin(1/x) - арккосеканс

Гиперболические тригонометрические функции

sinh(x)=(ex-e-x)/2 - гиперболический синус
asinh(x)=log(x+sqrt(x2+1)) - гиперболический арксинус
cosh(x)=(ex+e-x)/2 - гиперболический косинус
acosh(x)=log(x+sqrt(x2-1)) - гиперболический арккосинус
tanh(x)=(ex-e-x)/(ex+e-x) - гиперболический тангенс
atanh(x)=log((1+x)/(1-x))/2 - гиперболический арктангенс
coth(x)=(ex+e-x)/(ex-e-x) - гиперболический котангенс
acoth(x)=log((x+1)/(x-1))/2 - гиперболический арккотангенс
sech(x)=1/cosh(x)=2/(ex+e-x) - гиперболический секанс
asech(x)=acosh(1/x)=log[(1+sqrt(1-x2))/x] - гиперболический арксеканс
csch(x)=1/sinh(x)=2/(ex-e-x) - гиперболический косеканс
acsch(x)=asinh(1/x)=log[1/x+sqrt(1+x2)/abs(x)] - гиперболический арккосеканс

Функции округления

ceil(x) - округление вверх к ближайшему целому числу
floor(x) - округление вниз к ближайшему целому числу
round(x) - округление к ближайшему целому числу

Числа

Числа могут быть записаны в простой форме, например, 1.2. Точка используется как разделитель. Экспоненциальная форма представления чисел также допустима.

1.2e1=12
1.2e+1=12
1.2e-1=0.12
1.2e0=1.2
1.2e+0=1.2
1.2e-0=1.2

Скобки

Можно использовать три типа скобок ( ), [ ], { }

Java парсер

Первый пример

package demo;

import estimator.ExpressionEstimator;

public class Example1 {

  public static void main(String[] args){

    try {
      double v=ExpressionEstimator.calculate("sin(pi/4)");
      System.out.println(v);
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }

  }

}

Вывод

0.7071067811865475

Параметр функции calculate() - это формула которая может содержать переменные x0, x1, ... Если формула содержит переменные, то сначала ее необходимо скомпилировать. Затем вызвать функцию calculate(), передав значения неизвестных как аргумент.

package demo;

import estimator.ExpressionEstimator;

public class Example2 {

  public static void main(String[] args){
    ExpressionEstimator estimator=new ExpressionEstimator();
    try {
      estimator.compile("x0+x1");
      double[][]values={ {3,6}, {8,6} };
      for(double[]v:values){
        System.out.println( estimator.calculate(v) );
      }
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }

  }

}

Вывод

9.0
14.0

Более сложный пример

package demo;

import java.util.Arrays;

import estimator.ExpressionEstimator;

public class Example3 {

  public static void main(String[] args) throws Exception{
    String expression[]={"sin(pi/4)","1+2+"};
    for(String s:expression){
      System.out.print("\""+s+"\"=");
      try {
        System.out.println(ExpressionEstimator.calculate(s));
      } catch (Exception e) {
        System.out.println(e.getMessage());
      }
    }

    ExpressionEstimator estimator=new ExpressionEstimator();
    expression=new String[]{"3*x0+2*x1*x0","6*x0"};
    double[][]values={ {3,6}, {8,6} };
    double[]v;
    int i=0;
    for(String s:expression){
      v=values[i++];
      System.out.print("\""+s+"\""+Arrays.toString(v)+"=");
      try {
        estimator.compile(s);
        System.out.println(estimator.calculate(v));
      } catch (Exception e) {
        System.out.println(e.getMessage());
      }
    }

  }

}

Вывод

"sin(pi/4)"=0.7071067811865475
"1+2+"=unexpected operator
"3*x0+2*x1*x0"[3.0, 6.0]=45.0
"6*x0"[8.0, 6.0]=invalid number of expression arguments

C++ парсер

Первый пример

#include "expressionEstimator.h"
#include <stdio.h>

int main(){
  try {
    ExpressionEstimator::Init();
    double v=ExpressionEstimator::calculate("sin(pi/4)");
    printf("%lf",v);
  }catch(Exception& e){
    printf("%s\n",e.what());
  }
  return 0;
}

Вывод

0.7071067811865475

Параметр функции calculate() - это формула которая может содержать переменные x0, x1, ... Если формула содержит переменные, то сначала ее необходимо скомпилировать. Затем вызвать функцию calculate(), передав значения неизвестных и их количество как аргумент.

#include "expressionEstimator.h"
#include <stdio.h>

int main(){
  try {
    ExpressionEstimator::Init();
    ExpressionEstimator estimator;
    estimator.compile("x0+x1");

    const int arguments=2;
    const double values[][arguments]={ {3,6}, {8,6} };
    const int valuesSize=sizeof(values)/sizeof(values[0]);
    for(int i=0;i<valuesSize;i++){
      printf("%lf\n", estimator.calculate(values[i],arguments) );
    }
  }catch(Exception& e){
    printf("%s\n",e.what());
  }
  return 0;
}

Вывод

9.0
14.0

Более сложный пример

#include "expressionEstimator.h"
#include <stdio.h>
#include <string>

std::string arraytoString(const double *v,const int arguments){
  std::string s="[";
  char buff[32];
  for(int i=0;i<arguments;i++){
    sprintf(buff, "%lf", v[i]);
    s+=buff;
    s+= i==arguments-1 ? "]" : ", " ;
  }
  return s;
}

int main(){
  ExpressionEstimator::Init();
  ExpressionEstimator estimator;
  int i;
  const char*s;
  const char* expression[]={"sin(pi/4)","1+2+"};
  const int expressionSize=sizeof(expression)/sizeof(expression[0]);
  for(i=0;i<expressionSize;i++){
    s=expression[i];
    printf("\"%s\"=",s);
    try {
      printf("%lf\n",ExpressionEstimator::calculate(s));
    } catch (Exception& e) {
      printf("%s\n",e.what());
    }
  }

  const char* expression1[]={"3*x0+2*x1*x0","6*x0"};
  const int expression1Size=sizeof(expression1)/sizeof(expression1[0]);

  const int arguments=2;
  const double values[][arguments]={ {3,6}, {8,6} };
  const int valuesSize=sizeof(values)/sizeof(values[0]);

  const double*v;
  for(i=0;i<valuesSize;i++){
    v=values[i];
    s=expression1[i];
    printf("\"%s\"%s=",s,arraytoString(v,arguments).c_str());
    try {
      estimator.compile(s);
      printf("%lf\n",estimator.calculate(v,arguments));
    } catch (Exception& e) {
      printf("%s\n",e.what());
    }
  }

  return 0;
}

Вывод

"sin(pi/4)"=0.7071067811865475
"1+2+"=unexpected operator
"3*x0+2*x1*x0"[3.0, 6.0]=45.0
"6*x0"[8.0, 6.0]=invalid number of expression arguments

Javascript парсер

Чтобы использовать javascript парсер необходимо сначала включить script файл

<script src= type="text/javascript"></script>

а затем вызвать функцию calculate()

<html>
<head>
<script src= type="text/javascript">
</script>
<script type="text/javascript">
expression=["sin(pi/4)","1+2+"]
out=''
for(i=0;i<expression.length;i++){
  s=expression[i]
  out+='"'+s+'"='
  try {
    out+=calculate(s)
  } catch (exception) {
    out+=exception.message;
  }
  out+='\n'
}
alert(out);
</script>
</head>
<body>
</body>
</html>

Вывод

"sin(pi/4)"=0.7071067811865475
"1+2+"=syntax error

История версий

Первоначально программа разрабатывалась в мае-июле 2002 года как программа построения графиков на с++, после этого, параллельно шла разработка online калькулятора на javascript. Обе эти программы используют функцию парсинга выражений. В 2013 году было решено объединить эти два проекта и добавить к ним парсер строковых выражений (он создан на языках с++, java, javascript). Построение графиков теперь есть только на java. Калькулятор работает на c++, java и javascript.

версия 1.12 15 августа 2014

исправлены баги javascript

версия 1.11 17 июля 2014

исправлены баги c++ и javascript

версия 1.1 11 июля 2014

мелкие исправления в c++ коде
добавлен калькулятор на c++ на GTK+

версия 1.04 1 мая 2014

исправлены баги в калькуляторе на javascript
добавлена поддержка всех функций в калькуляторе на javascript
исправлен баг в функции acsch

версия 1.03 20 апреля 2013

изменен интерфейс построителя графиков

версия 1.01-1.02 17 апреля 2013

добавлен исходный код парсера на c++ и javascript

версия 1.0 22 февраля 2013

проекты (калькулятор, построитель графиков и калькулятор) объединены
код построителя графиков переписан с c++ на java