Jump to content

string based math


taith

Recommended Posts

question here...

 

say we have a string coming from a form, already verified that its numeric/mathmatical(+-*/) how can we then process that into an answer without using eval?

 

$string='1+2*3';
echo process($string); #7

 

If eval() is the answer, you're almost certainly asking the wrong question. -- Rasmus Lerdorf, BDFL of PHP
Link to comment
Share on other sites

forgive my ignorance... but what does compilers have to do with parsing a math string into an answer?

 

and yes, i agree... for higher grade calculators(graphing, etc), they parse the string input into an answer...

 

tho the question was how they did it... not what they did... im just looking for a prod in the right direction :)

Link to comment
Share on other sites

forgive my ignorance... but what does compilers have to do with parsing a math string into an answer?

 

It has everything to do with it even though it's just a simple DSL.

 

You first need to do some sort of lexical analysis. You need to figure out what is an operator and what is an operand. You'll then need to do some sort of semantic analysis figuring out what do with the various tokens when given in that particular order. In the case of a math parser you would have to take things like operator precedence into account (at least using the notation you used) for instance. You would then need to do some sort of type checking, i.e. you would need to ensure that operands are only numeric values (or variables containing or referring to numeric values if you choose to implement that).

 

The fact that it's a simple language (as long as you constrain yourself to the arithmetic operators on real numbers) doesn't mean it's not a language. A computer doesn't intuitively understand math, so you need to tell it how to interpret it and that is done using a compiler or interpreter (though the first part of a compiler and interpreter is usually identical).

Link to comment
Share on other sites

whats wrong with eval ? apart from not getting any error codes ????, if your a good programmmer you dont need error codes lol, my website when you click the tree panel node, it ajaxes in the code for the module and then evals it which forces it to manipulate the current page, this can be the basis of a whole architecture.

 

 

a page that never leaves the resource but talks to other resources and then does what they say to change itself, its just a front end it dosent matter it just needs to change into the intended form.

 

if all your resources are controllers and methods then this architecture is great.

 

its a data based application so maybe its diff for websites

Link to comment
Share on other sites

PHPExcel has a built in calculation engine that can handle formulae in this manner.

The current release version builds a PHP lambda function based on parsing the formula. The latest development version parses the formula to a stack using Dijkstra's "shunting yard" algorithm, and then stack evaluation.

 

If PHPExcel is overkill for your more simple formulae, then there's always an EvalMath class on phpclasses that works in a similar fashion.

 

 

Link to comment
Share on other sites

Nadeem, that utterance is self contradicting. Your premise is that you might as well use eval(), but you say a good programmer don't need error messages. I interpret this to mean that you say you should validate that it's in the correct format, but that requires the parsing that you were trying to get around. So you are in a way answering the question yourself.

 

code not withstanding... i think we're talking about something like this

 

turning

1+2*(3+4)

 

into

1+(2*(3+4))

 

solve the brackets deep to shallow and you'll have your answer...? hmmm

 

I'm not sure I understand what you mean. Even if you required your users to only enter the latter you would still have to figure out what is what, i.e. what is an operator, what denotes parentheses and what could be regarded as numbers. You would then also have to figure out what these tokens in that sequence mean semantically and you would need to verify that it's a valid statement in the first place. It may simplify the parsing not having to take operator precedence into account, but that doesn't change the fact that you still have to parse it somehow.

Link to comment
Share on other sites

My naive mind can only comprehend, objects, function calls, regex and parsers, somone please try and riddle me this because i cant get it off my mind now, how would you use the posted string without evaluating it ?? and not using any of the previouse listed by me. I sense Dan is hinting somthing.

 

Dan:

 

He said hes using so its going to be parsed no matter what, its a matter of weather you want to parse the string as a string or as code.

 

Maybe im not seing past the garden fence here.

 

I am sure i have come accross the answer to this ON THIS FORUM before. Its some obsured concatination with slashes.

Link to comment
Share on other sites

Well, the thing is that he is trying to implement a simple math DSL and running it through eval() doesn't accomplish this. Even if he did he would still have to parse and verify that it's a correct format, in which case he might as well just finish the interpreter.

Link to comment
Share on other sites

As a starting point i dont know if the regex is right, you need the position and ocurunce of each line word and char

function process($string){
      $lines = preg_split("\s", $string);
  foreach($lines as $line_k => $line_v){
		$words = preg_split(" ", $line_v);
		foreach($words as $word_k => $word_v){
			$characters = preg_split(".", $word_v);
			foreach($characters as $character_k => $character_v){
			           echo "line No.:".$line_k." Word No.:".$word_k." Charachter:".$character_v."<br>";
			}
		}
  }
}

$string = "1+2*3";

echo process($string);

 

 

Dan, can you not use somting like when you use int to force an int from a value, isnt there like opperator

Link to comment
Share on other sites

maybe somthing like this

split all the numbers out of the string into an array, using

 

 

 


myFunc(preg_split("[0-9]",$string), preg_split("\D",$string));

function myfunc(array $arrayOperators , array $arrayNumbers){

foreach($arrayNumbers as $n_k => $n_v){
	switch ($arrayOperators[$n_k]) {
		case "+":
			add($n_v);
			break;
		case "-":
			sub($n_v);
			break;
		case "*":
			times($n_v);
			break;
	}
}

             return $_SESSION['n'];
} 


function  add($n_new){
$n = $_SESSION['n'];
if(!n) $n=0;
$r = $n + $n_new;
$_SESSION['n'] = $r;
return $r;
}

Link to comment
Share on other sites

Regexp would probably be the path I would take....

 

 

I would do something like this:

 

 

Write a function that parses simple statements....

 

 

All it would do would be parse out a+b to c and parse out a*b to c if you know what I mean....

 

 

For example:

 

 

5+3*2 would be parsed to 11.

 

 

But first I would have some code pull out all of the groups and have them parsed down.

 

 

For example:

 

(5+5)*2

 

Would be parsed to:

 

10*2

 

 

Or

 

((5+(2+2)*2)*3)

 

Would be parsed to:

 

(5+4*2)*3

 

Then

 

(5+8)*3

 

Then 39.

 

 

 

Hrmmm....  I came up with something that's not exactly pretty, but it works...

 


<?php

echo calc("5+2+(5+5*(2+5*1))");
//5+2+(5+5*(2+5*1)) -> 5+2+(5+5*(2+5)) -> 5+2+(5+5*(7)) -> 5+2+(5+35) -> 5+2+(40) -> 7+(40) -> 47

/*
//Dual core 2.8ghz processor with slow RAM:
//Total time for 3 tests with 10000 iterations each: 7.7037310600281
//Average time per test: 0.77037310600281
//Average time per execution: 0.0000770373
$times = array();

define('TESTS', 3);
define('ITERATIONS', 10000);

for($t = 0; $t < TESTS; ++$t) {
$START = microtime(true);
for($i = 0; $i < ITERATIONS; ++$i) {
	calc("5+2+(5+5*(2+5*1))");
}
$END = microtime(true);
$times[] = $END - $START;
}

$total = array_sum($times);

echo "Total time for " . TESTS . " tests with " . ITERATIONS . " iterations each: $total\n";
echo "Average time per test: " . ($total/10) . "\n";
echo "Average time per execution: " . sprintf('%.10f', ($total/10/ITERATIONS)) . "\n\n";
*/


function calc($expr) {
//this entire function is horribly ineffecient
//Get rid of space and change a,bcd.ef into abcd.ef
$expr = preg_replace('/\s|,/', '', $expr);
//this changes (x) to plain x....  So if you have like 5+(3) it will be changed into 5+3.
if(preg_match('/^\(([\d]+)\)$/', $expr, $m)) {
	return $m[1];
}
//Blerh, I don't feel like adding support for (a)b and so on....
$expr = preg_replace('~\(([0-9\+\-\*\/]+)\)~e', 'calc("\1")', $expr);
//This is to parse out numbers left in the form a+(b) or (a)-b so on....
do {
	//Yeah, this should definitely be coded better....
	$expr = preg_replace(
		array(
			'~(\d+)\/(\d+)~e',
			'~(\d+)\*(\d+)~e',
			'~(\d+)-(\d+)~e',
			'~(\d+)\+(\d+)~e',
		),
		array(
			"div('$1', '$2')",
			'mul("$1", "$2")',
			'sub("$1", "$2")',
			'add("$1", "$2")',
		),
		$expr,
		-1,
		$c
	);
	$expr = preg_replace('~(\b|\+|\-|\*|/)\(([\d]+)\)~', '$1$2', $expr);
}
while ($c != 0);
//This has to be done again since something could result in it.
return $expr;
}


//Well...  I never said my solution was pretty ;p

function add($a, $b) { return $a + $b; }
function sub($a, $b) { return $a - $b; }
function mul($a, $b) { return $a * $b; }
function div($a, $b) { return $a / $b; }

Link to comment
Share on other sites

When i was writing my one i was thinking about the processor and how it holds values and then performs logic to increase the binary state of its representation.

 

Corbin even though your one is much better at doing what it does i do think there is an element of loosing the meaning of number and confusing it with string in your one.

 

i was trying to invasion all characters being equal as we are turning this string into a formula so i didn’t want to chop things after i had spited them.

 

 

Imagine you have a listening port that takes in char by char.

 

it takes in 1 it buts it into the back burner it takes in a + now it must go back to that one and plus it to something witch is nothing the next char come sin and its a 2 so its takes the result from the previous and adds that to the 2 if a bracket came in it would start a new session value to hold the sub equation and it would put each sub equation into a an array  (this is where the hard part is that you have accomplished well done) . etc etc

 

 

i think by using preg_replace in this instance you are lying to yourself lol ;)

 

 

 

 

for the OP - you could try spliting them by the () and only taking the inner equasions using regex but then you would have to do some research scientific research in how you would combine these back together eg, what array element (blah) result goes back in wich place to form the final equasion, i think corbin handeled it but , not as it is done in processors or scriptprocessors

Link to comment
Share on other sites

  • 1 year later...

Doesn't this solve the problem:

$string='1+2*3';

eval("\$string=$string;");

echo $string;

 

This gives the same result:

$var1=1;

$var2=2;

$var3=3;

$string='$var1+$var2*$var3';

eval("\$string=$string;");

echo $string;

 

Both echos 7!

 

Hopefully this helps somebody out there! =)

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.