калькулятор сложных вычислений

надо создать калькулятор. понимаю, что создавать его на php нецелесообразно, но делаю просто для себя, что бы поучиться =)
только вот калькулятор не простой, где на кнопочки жмешь типо "+""-" и тд, а с изюминкой:
есть input, в него ввожу выражение, типо 2+2(6^2*8-4)+7/4. ну а вылезти мне должен,конечно же, результат =)
читала про польскую обратную запись, вещь конечно хорошая, но не заставлю же я пользователя вводить так данные.
вот и вопрос: как же это провернуть? какой алгоритм? подскажите кто сталкивался)
 

WMix

герр M:)ller
Партнер клуба
НатальяПавлинкович
если калькулятор для себя пишешь можно простым eval решить. только вот ^ нужно на pow поменять ну и знаки всегда писать
PHP:
$_GET['expr'] = '2+2*(pow(6,2)*8-4)+7/4';
$phpexpr = '$str = '.$_GET['expr'].';';
eval($phpexpr);
echo $str. "\n";
 
что-то получилось, только вот вопросы все равно есть =( в function convert в комментах
еще не знаю как скобки прописать (
PHP:
<?php
$expr=$_POST['expression'];
function convert(){  //преобразую из инфиксной нотации в ОПН
	$exp0=chunk_split($exp); //?разбить строку на символы
	$stack0=array(); //стэк
	$exit=array(); // выходная строка
		while (count($expr0)!==0){
		if is_numeric($exp0){
			array_push($exit, $exp0);
		} elseif (in_array($exp0, array('*','/','+','-'))) {
			array_push($stack0, ); // добавить этот знак в стэк
		}
	}
    return array_push($exit, $stack0);
}


function calc($str){ //считаю само выражение в ОПН
    $stack = array();
    $token = strtok($str, ' ');
    while ($token !== false){
        if (in_array($token, array('*', '/', '+', '-'))){
            $b = array_pop($stack);
            $a = array_pop($stack);
            switch ($token){
                case '*': $res = $a*$b; break;
                case '/': $res = $a/$b; break;
                case '+': $res = $a+$b; break;
                case '-': $res = $a-$b; break;
            }
            array_push($stack, $res);
        } elseif (is_numeric($token)){
            array_push($stack, $token);
        } 
        $token = strtok(' ');
    }
    return array_pop($stack);
}
echo calc($expr);
 ?>
 

Вурдалак

Продвинутый новичок
Код явно не запускался. Разбиение на токены неправильное, например. Там проще через preg_split:
PHP:
$tokenList = preg_split('#([+\-*/\^()]|\d+)#', '2+2(6^2*8-4)+7/4', -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
 

riff

Новичок
http://pastebin.com/NEMkqC4R
пример:
PHP:
class MyCalc extends Calculator
{
	/**
	 * определяем пользовательские переменные
	 * @override
	 */
	public function cb_var($value)
	{
		switch ($value)
		{
			case 'my_var':
				return 'abc';
			default:
				return parent::cb_var($value);
		}
	}

	/**
	 * определяем пользовательские функции
	 * @override
	 */
	public function cb_func($name, $args)
	{
		switch ($name)
		{
			case 'my_zzz':
				return 'zzzzzzz';
			case 'my_plus':
				return (int)$args[0] + (int)$args[1];
			default:
				return parent::cb_func($name, $args);
		}
	}
}

//если достаточно стандартного калькулятора
//$calc = new Calculator(null);

//создаём свой калькулятор с расширенным набором функций
$calc = new MyCalc(null);

echo $calc->Calc('(1 + 2) / 3 +  9 * 5');
//echo $calc->Calc('2+2(6^(1+1)*8-4)+7/4'); //степень
//echo $calc->Calc("(1 + 2)^3 * 5 + ' Текст'"); //вычисления + текст
//echo $calc->Calc("@replace('дороге', 'шоссе', 'Шла Саша по дороге')"); //замена текста
//echo $calc->Calc('(1+2)/3+9+@my_zzz()'); //вызов пользовательской функции
//echo $calc->Calc('(1+2)/3+9+@my_plus(100, 25)'); //вызов пользовательской функции с параметрами

//вызов пользовательской переменной, а так же тернарное выражение
//echo $calc->Calc("'Какой-то текст ' + ([my_var]='abc' ? 'true' : 'false')"); //= (равно), != (не равно), < (меньше), > (больше)
И ещё, модуль был написан ооочень давно, написан для сайта где надо было что-то высчитывать, + текст к ячейкам таблицы добавлять то такой, то сякой, ну и т.д., и в одной таблице так, в другой иначе... короче, проще всё это(формулы вычислений значений ячеек) было легче загнать в шаблоны табличек и в них прописать те или иные формулы ячейкам.
 

riff

Новичок
: ) Я знаю эту статью на lurkmore. Нет, не потому, что сообщение от "она", просто было здесь и сейчас.
 

hell0w0rd

Продвинутый новичок
Вурдалак
Где?)
Можно передавать параметры) Это веселее чем eval:)
Если бы у меня была такая лаба, и учили бы мы php в инсте, ограничение явно было бы только на eval - только так и сделал бы)
 

Вурдалак

Продвинутый новичок
Это обёртка над eval, атавизм со времён отсутствия замыканий. А то так можно ведь и записать во временный файл и приинклудить или через preg_replace('//e') «решить». Ну, нормальный препод бы тебя поимел.
 
Сверху