taith Posted July 27, 2009 Share Posted July 27, 2009 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 Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/ Share on other sites More sharing options...
Daniel0 Posted July 27, 2009 Share Posted July 27, 2009 http://en.wikipedia.org/wiki/Compiler http://en.wikipedia.org/wiki/Interpreter_%28computing%29 Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-883955 Share on other sites More sharing options...
vineld Posted July 27, 2009 Share Posted July 27, 2009 That's kind of the basics of creating a calculator. You need to parse the string. This is usually done in beginner's programming courses at university over here (Sweden). Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-883960 Share on other sites More sharing options...
taith Posted July 27, 2009 Author Share Posted July 27, 2009 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 Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-883971 Share on other sites More sharing options...
Daniel0 Posted July 27, 2009 Share Posted July 27, 2009 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). Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-883976 Share on other sites More sharing options...
taith Posted July 27, 2009 Author Share Posted July 27, 2009 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 Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-883980 Share on other sites More sharing options...
nadeemshafi9 Posted July 27, 2009 Share Posted July 27, 2009 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 Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-883983 Share on other sites More sharing options...
Mark Baker Posted July 27, 2009 Share Posted July 27, 2009 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. Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-883986 Share on other sites More sharing options...
Daniel0 Posted July 27, 2009 Share Posted July 27, 2009 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. Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-883989 Share on other sites More sharing options...
nadeemshafi9 Posted July 27, 2009 Share Posted July 27, 2009 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. Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-884183 Share on other sites More sharing options...
Daniel0 Posted July 27, 2009 Share Posted July 27, 2009 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. Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-884197 Share on other sites More sharing options...
nadeemshafi9 Posted July 27, 2009 Share Posted July 27, 2009 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 Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-884204 Share on other sites More sharing options...
nadeemshafi9 Posted July 27, 2009 Share Posted July 27, 2009 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; } Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-884230 Share on other sites More sharing options...
corbin Posted July 27, 2009 Share Posted July 27, 2009 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+*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; } Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-884246 Share on other sites More sharing options...
nadeemshafi9 Posted July 27, 2009 Share Posted July 27, 2009 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 Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-884263 Share on other sites More sharing options...
corbin Posted July 27, 2009 Share Posted July 27, 2009 Losing the meaning of number and confusing it with string..... No, I didn't confuse anything. Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-884269 Share on other sites More sharing options...
MMDE Posted November 21, 2010 Share Posted November 21, 2010 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! =) Quote Link to comment https://forums.phpfreaks.com/topic/167624-string-based-math/#findComment-1137524 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.