GithubHelp home page GithubHelp logo

madorin / matex Goto Github PK

View Code? Open in Web Editor NEW
110.0 9.0 34.0 31 KB

PHP Mathematical expression parser and evaluator

License: MIT License

PHP 100.00%
math-expression-evaluator expression-evaluator expression-engine evaluator matex concatenation eval formula calculator

matex's Introduction

License

Matex

PHP Mathematical expression parser and evaluator

Features

  • Fast evaluation
  • Compact codebase
  • Operators: + - * / ^ %
  • Brackets, nested, unlimited levels
  • Variables: predefined or estimated dynamically
  • Functions: predefined or connected dynamically
  • String arguments in functions, like field("name")
  • String operations, currently concatenation is supported

Installation

Using Composer run

$ composer require madorin/matex

See manual for more details and options.

Usage

Basic:

$evaluator = new \Matex\Evaluator();
echo $evaluator->execute('1 + 2');

String concatenation:

$evaluator = new \Matex\Evaluator();
echo $evaluator->execute('"String" + " " + "concatenation"');

Variables:

$evaluator = new \Matex\Evaluator();
$evaluator->variables = [
	'a' => 1,
	'b' => 2
	];
echo $evaluator->execute('a + b');

Dynamic variables:

public function doVariable($name, &$value) {
	switch ($name) {
		case 'b':
			$value = 2;
			break;
	}
}

$evaluator = new \Matex\Evaluator();
$evaluator->variables = [
	'a' => 1
	];
$evaluator->onVariable = [$this, 'doVariable'];
echo $evaluator->execute('a + b');

Functions:

static function sum($arguments) {
	$result = 0;
	foreach ($arguments as $argument)
		$result += $argument;
	return $result;
}

$evaluator = new \Matex\Evaluator();
$evaluator->functions = [
	'sum' => ['ref' => '\\Space\\Class::sum', 'arc' => null]
];
echo $evaluator->execute('sum(1, 2, 3)');

Extravaganza:

/*
Dynamic variable resolver
Invoked when the variable is not found in the cache
Returns the value by name
*/
public function doVariable($name, &$value) {
	switch ($name) {
		case 'zen':
			// Here may be a database request, or a function call
			$value = 999;
			break;
		case 'hit':
			$value = 666;
			break;
	}
}

/*
Dynamic function resolver
Invoked when the function is not found in the cache
Returns an associative array array with:
	ref - Function reference
	arc - Expected argument count
*/
public function doFunction($name, &$value) {
	switch ($name) {
		case 'cos':
			// Map to a system function
			$value = ['ref' => 'cos', 'arc' => 1];
			break;
		case 'minadd':
			// Map to a public object instance function
			$value = ['ref' => [$this, 'minAdd'], 'arc' => 2];
			break;
	}
}

/*
Custom functions, may be a
	- Built-in function
	- Global defined function
	- Static class function
	- Object instance function
*/
static function sum($arguments) {
	$result = 0;
	foreach ($arguments as $argument)
		$result += $argument;
	return $result;
}
// Just a sample custom function
function minAdd($a, $b) {
	$r = $a < 2 ? 2 : $a;
	return $r + $b;
}

// Let's do some calculations
$evaluator = new \Matex\Evaluator();
$evaluator->variables = [
	'a' => 1,
	'bet' => -10.59,
	'pi' => 3.141592653589
	];
$evaluator->onVariable = [$this, 'doVariable'];
$evaluator->functions = [
	'sin' => ['ref' => 'sin', 'arc' => 1],
	'max' => ['ref' => 'max', 'arc' => null],
	'sum' => ['ref' => '\\Space\\Class::sum', 'arc' => null]
	];
$evaluator->onFunction = [$this, 'doFunction'];
echo $evaluator->execute('a + MinAdd(PI * sin(zen), cos(-1.7 / pi)) / bet ^ ((A + 2) * 2) + sum(5, 4, max(6, hit))');

See examples for code samples.

Author

Dorin Marcoci - [email protected] - https://www.marcodor.com

License

Matex is distributed under MIT license.

matex's People

Contributors

madorin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

matex's Issues

Rounding

Is your feature request related to a problem? Please describe.
Currently its not possible to round

Describe the solution you'd like
Will be awesome if there is a way to use it that way for example i want to do round(0.7/100) or something else..

Describe alternatives you've considered
Currently im using plain php, will like to switch to a lib like this so i can create dynamic calculations via user inputs for example.

Additional context
Is there any alternative package to this that supports round? I couldn't find any maybe im searching the wrong keywrods.

Add composer.json and add this to https://packagist.org/

Is your feature request related to a problem? Please describe.
This project looks really handy, but without having it on https://packagist.org/ it makes installing and maintenance very old school. E.g. my current laravel project I have to download the files and manually autoload them.

Describe the solution you'd like
Please can you add a composer.json file to the project and submit the project to https://packagist.org/ This would allow for easier installation and maintenance, when used inside other projects.

Describe alternatives you've considered
There ain't one

Additional context

No License

It would be fantastic if the project will be released under a license. I would like to use the well written code.
More Info

Handle invalid operations

Adding a number and a string now produces a php warning.

e.g.:

$evaluator = new \Matex\Evaluator();

try {
    $evaluator->execute('1 + "x"');
} catch(Exception $exception) {
    // ....
}

It would be nice to have a catchable exception when the terms do not match and the calculation is invalid.

Problem calcul simple addition

Hi,

I have a problem when calculate simple sum :
$evaluator = new \Matex\Evaluator();
$evaluator->execute('0.37+0.31-0.68');

The result must be "0", but it return : "-1.1102230246252E-16"

Have you an idea of why ?

Thanks

Make variables case sensitive (not only Lower Case)

Is your feature request related to a problem? Please describe.
I have a use case where my variables are UCased (i.e. A, B, ...). I was surprised to have to use strict Lcase variables because your Evaluator is LCasing the formula passed to it.

Describe the solution you'd like
Let the user choose the case sensitivity via an option and by default use the exact formula that the user provides (no LCasing).
OR
LCase all variables passed to the evaluator (this one is not my favorite).

Describe alternatives you've considered
N/A

Additional context
N/A.

Assign a value to a variable inside an expression

Not entirely sure whether this is a bug or a feature request.

In my code I have:

$this->matex->execute('a=random()');

Unfortunately, this throws an exception: Exception: Unknown variable: a in Evaluator->getVariable(). Am I correct that this is not supposed to work in the current version?

Can't handle negative numbers

Try to use a negative number in the equation.

5 + (-0.5) produces an error when it should result to 4.5.
5 + -0.5 produces an error when it should result to 4.5.

Not working with multiples of 10

So every time it executes an equation with zeros mostly, it doesn't work. If I execute just '10' it will give me just the multiplication of 10 ( so 1 for 10, 2 for 20 ) and that's all. Also, getting floats like 0.5 into the equation will give an error. So there's a problem whenever 0 is present.

Exception: Empty argument in Evaluator->addArgument() when custom function without arguments

I have and EvalMathFunctions class, holding a 'random' function without arguments.

class EvalMathFunctions {
  static public function random() {
    return rand();
  }
}

I register this in matex:

$this->evaluator->functions = [
  'random' => ['ref' => '\\EvalMathFunctions::random', 'arc' => 0]
];

I then call the function:

$this->evaluator->execute('random()');

And get the error.

Order of operations between powers and multiplications

Describe the bug
The order of operations between powers and multiplications is not what I expect

To Reproduce
Steps to reproduce the behavior:

$evaluator = new \Matex\Evaluator();
$evaluator->execute(4*3^2); // returns 144
$evaluator->execute(45/3^2); // returns 225

Expected behavior
Following usual PEDMAS order of operations, powers should be computed before multiplications and/or divisions.
The above code should then return 36 on line 2 and 5 on line 3

Support comparison operators (>, <, =, >=,<=) to get a true / false evaluation

Is your feature request related to a problem? Please describe.
This feature request is related to a use case. I need to implement price calculation depending on some variables. A price can be obtained through various formula. Each formula has a condition of application (e.g a+b+c > 200 then use formula 1 - I need to be able to evaluate the formula a+b+c > 200)

Describe the solution you'd like
Take the comparison operators into account.

Describe alternatives you've considered
N/A

Additional context
N/A.

Examples difficult to understand

This is only a suggestion, but I needed time to understand examples. I suggest you to remove the object requirement. For function example :

function sum() {
$arguments = func_get_args();
$result = 0;
foreach ($arguments as $argument)
$result += $argument;
return $result;
}
$evaluator = new \Matex\Evaluator();
$evaluator->functions = [
'sum' => ['ref' => 'sum', 'arc' => null]
];
echo $evaluator->execute('sum(1, 2, 3)');

Example given does't work

static function sum($arguments) {
	$result = 0;
	foreach ($arguments as $argument)
		$result += $argument;
	return $result;
}

$evaluator = new \Matex\Evaluator();
$evaluator->functions = [
	'sum' => ['ref' => '\\Space\\Class::sum', 'arc' => null]
];
echo $evaluator->execute('sum(1, 2, 3)');

In the function sum, when I output $arguments, I only get the first value (1, in this case).
How do I get array of all the arguments?

Custom basic operators

I'd like to have a modulo operator, but I would generalise and say it would be nice if we could add custom functions which behave like the basic operators, that being that you call them like a op b instead of op(a, b).

Could not evaluate "2*0*0.45*0.3*7.4999999999999997E-2"

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

Code can't handle round brackets in strings

Describe the bug
Unmatched brackets exception for a simple string concatenation.

To Reproduce
Steps to reproduce the behavior:
execute('"(" + "xyz"')

Expected behavior
execute function tests for unmatched brackets but does not ignore brackets within a "string" - bracket checking should occur per expression parsed.

Screenshots
n/a

Desktop (please complete the following information):
n/a

Smartphone (please complete the following information):
n/a

Additional context
Add any other context about the problem here.

( 101.25 + -202.44 ) results in "syntax error"

Describe the bug
( 101.25 + -202.44 ) = syntax error

To Reproduce


$evaluator = new \Matex\Evaluator();
$error = FALSE;
try {
	$val = $evaluator->execute("( 101.25 + -202.44 )");
} catch ( \Exception $e ) {
	$error = $e->getMessage();
	$val = "__";
}
echo $val;
echo $error;

Expected behavior
return -101.19 and not error out

Desktop (please complete the following information):

  • OS: windows 10. php 7.2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.