Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Калькулятор выражений

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
Negaty
Отправлено: 19 Апреля, 2013 - 01:09:32
Post Id


Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Апр. 2013  


Помог: 0 раз(а)




ребята, помогите пожалуйста, надо написать калькулятор выражений типа: 3+4-8/2
т.е. в input вводиться это выражение, нажимаю на submit и оно считается.
только есть одно но: не использовать eval
я новичок, только пытаюсь освоить php и этот калькулятор нужен в учебных целях =)
спасибо всем, кто ответит. Улыбка
 
 Top
Skycrafter
Отправлено: 19 Апреля, 2013 - 05:13:25
Post Id



Гость


Покинул форум
Сообщений всего: 85
Дата рег-ции: Март 2013  


Помог: 2 раз(а)




поспешил

(Отредактировано автором: 19 Апреля, 2013 - 05:19:12)



-----
Тысячемильный путь начинается с первого шага...
 
 Top
Medallion
Отправлено: 19 Апреля, 2013 - 16:26:17
Post Id



Частый гость


Покинул форум
Сообщений всего: 253
Дата рег-ции: Май 2012  
Откуда: Херсон, Украина


Помог: 7 раз(а)




Просто в php умножение и деление бери в скобки, тоесть в input заганяй в таком виде: 3+4-(8/2) и php будет считать.
 
 Top
DelphinPRO
Отправлено: 19 Апреля, 2013 - 16:38:47
Post Id



Активный участник


Покинул форум
Сообщений всего: 7187
Дата рег-ции: Февр. 2012  


Помог: 353 раз(а)




пишем лексический анализатор ru.wikipedia.org/wiki/Рекурсивны й_нисходящий_парсер
( Конечный автомат для парсера удобно будет рисовать в этой программке - http://www[dot]yworks[dot]com/en/products_yed_about[dot]html )
отдаем ему на вход выражение, на выходе получаем поток токенов (лексем)
поток токенов отдаем на вход синтаксического анализатора, который проверит корректность выражения. на выходе получаем синтаксическое дерево с данными. Рекурсивно обрабатываем полученные данные, вычисляя значение выражения. Профит!

в общем, фигня делов - вечерок посидеть.

PS А вы уверены, что для освоения php вам нужно написать именно калькулятор? Задачка, в общем-то не простая, с наскока не решить.

(Отредактировано автором: 19 Апреля, 2013 - 16:42:05)



-----
Чем больше узнаю, тем больше я не знаю.
 
 Top
Negaty
Отправлено: 20 Апреля, 2013 - 04:25:08
Post Id


Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Апр. 2013  


Помог: 0 раз(а)




что-то попыталась сделать: получилось как-то так.
вопросы в функции convert, еще не знаю как скобки прописать(
там одна фукция из инфиксной записи перефодит в обратную польскую нотацию, вторая считает выражение.
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. $expr=$_POST['expression'];
  3. function convert(){  //преобразую из инфиксной нотации в ОПН
  4.         $exp0=chunk_split($exp); //?разбить строку на символы
  5.         $stack0=array(); //стэк
  6.         $exit=array(); // выходная строка
  7.                 while (count($expr0)!==0){
  8.                 if is_numeric($exp0){
  9.                         array_push($exit, $exp0);
  10.                 } elseif (in_array($exp0, array('*','/','+','-'))) {
  11.                         array_push($stack0, ); // добавить этот знак в стэк
  12.                 }
  13.         }
  14.     return array_push($exit, $stack0);
  15. }
  16.  
  17.  
  18. function calc($str){ //считаю само выражение в ОПН
  19.     $stack = array();
  20.     $token = strtok($str, ' ');
  21.     while ($token !== false){
  22.         if (in_array($token, array('*', '/', '+', '-'))){
  23.             $b = array_pop($stack);
  24.             $a = array_pop($stack);
  25.             switch ($token){
  26.                 case '*': $res = $a*$b; break;
  27.                 case '/': $res = $a/$b; break;
  28.                 case '+': $res = $a+$b; break;
  29.                 case '-': $res = $a-$b; break;
  30.             }
  31.             array_push($stack, $res);
  32.         } elseif (is_numeric($token)){
  33.             array_push($stack, $token);
  34.         }
  35.         $token = strtok(' ');
  36.     }
  37.     return array_pop($stack);
  38. }
  39. echo calc($expr);
  40.  ?>
 
 Top
Negaty
Отправлено: 21 Апреля, 2013 - 14:30:40
Post Id


Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Апр. 2013  


Помог: 0 раз(а)




получилось так, только вот перевод в обратную польскую запись все равно не правильный(
он сначала берет все числа и записывает их, а потом к ним прибовляет все знаки =( так не должно быть...
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. $exp=$_POST['expression'];
  3. function convert($exp){  //преобразую из инфиксной нотации в ОПН
  4.     $expArr=preg_split('#([+\-*/\^()]|\d+)#', $exp, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); //разбить строку на символы
  5.     $stack0=array(); //стэк
  6.     $exit=array(); // выходная строка
  7.     foreach($expArr as $exp0){
  8.         if( is_numeric($exp0)){
  9.             $exit[]=$exp0;
  10.         } elseif (in_array($exp0, array('*','/','+','-'))) {
  11.             $stack0[]=$exp0;
  12.         }
  13.     }
  14.     $exprArray=array_merge($exit, $stack0);
  15.     $expr=implode(" ", $exprArray);
  16.     return $expr;
  17. }
  18.  
  19.  
  20.  
  21. function calc($str){ //считаю само выражение в ОПН
  22.     $stack = array();
  23.     $token = strtok($str, ' ');
  24.     while ($token !== false){
  25.         if (in_array($token, array('*', '/', '+', '-'))){
  26.             $b = array_pop($stack);
  27.             $a = array_pop($stack);
  28.             switch ($token){
  29.                 case '*': $res = $a*$b; break;
  30.                 case '/': $res = $a/$b; break;
  31.                 case '+': $res = $a+$b; break;
  32.                 case '-': $res = $a-$b; break;
  33.             }
  34.             array_push($stack, $res);
  35.         } elseif (is_numeric($token)){
  36.             array_push($stack, $token);
  37.         }
  38.         $token = strtok(' ');
  39.     }
  40.     return array_pop($stack);
  41. }
  42.    $str=convert($exp);
  43.    echo calc($str);
  44.  ?>
 
 Top
Negaty
Отправлено: 22 Апреля, 2013 - 01:31:56
Post Id


Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Апр. 2013  


Помог: 0 раз(а)




еще появились обнавления, только вот проблемы с корнем, возведением в степень... (
ну и скобки так не могу добить =(
PHP:
скопировать код в буфер обмена
  1. $exp=$_POST['expression'];
  2. function convert($exp){  //преобразую из инфиксной нотации в ОПН
  3.     $expArr=preg_split('#([+\-*/\^()]|\d+)#', $exp, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); //разбить строку на символы
  4.     $stack0=array(); //стэк
  5.     $exit=array(); // выходная строка
  6.     $prev='';
  7.     foreach($expArr as $exp0){
  8.     //for ($i=0; $i<=count($expArr); $i++)
  9.         if( is_numeric($exp0)){
  10.             $exit[]=$exp0;
  11.         } elseif (in_array($exp0, array('*','/','+','-','('))) {
  12.             if (prior($exp0)==1){
  13.                 $stack0[]=$exp0;
  14.             } elseif (prior($exp0)==2) {
  15.                 if (prior($prev)<2){
  16.                 $stack0[]=$exp0;
  17.                 } else {
  18.                 $exit[]=$prev;
  19.                 array_pop($stack0);
  20.  
  21.                 $stack0[]=$exp0;
  22.                 }              
  23.             } elseif (prior($exp0)==3) {
  24.                 if (prior($prev)<3){
  25.                 $stack0[]=$exp0;
  26.                 } else {
  27.                 $exit[]=$prev;
  28.                 array_pop($stack0);
  29.  
  30.                 $stack0[]=$exp0;
  31.                 }
  32.                         $prev=$exp0;
  33.             }  
  34.         }
  35.         // if (in_array($exp0, ')')){   // непонятное действие со скобками
  36.         //     while (array_pop($exp0)!='('){
  37.         //         $exit[]=array_pop($exp0);
  38.         //     }
  39.         // }
  40.     }
  41.  
  42.     $exprArray=array_merge($exit, array_reverse($stack0));
  43.     $expr=implode(" ", $exprArray);
  44.     return $expr;
  45. }
  46. echo 'RESULT='.convert($exp);
  47.  
  48. function prior($stack0){
  49.     switch ($stack0) {   // пытаюсь расставить приоритеты
  50.         case '(': return 1; break;
  51.         case '+' and '-': return 2; break;
  52.         case '*' and '/': return 3; break;
  53.         // case '^': return 4; break;  
  54.         default: return 0;
  55.     }
  56. }

(Добавление)
но походу никто не читает =(
(Добавление)
ну и функция calc =) там изменений нет
 
 Top
EuGen Администратор
Отправлено: 22 Апреля, 2013 - 09:17:07
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Вещь любопытная. Возможно, создам подобный анализатор на досуге, тем более что в теоретическом плане оно полезно.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
DelphinPRO
Отправлено: 22 Апреля, 2013 - 09:32:46
Post Id



Активный участник


Покинул форум
Сообщений всего: 7187
Дата рег-ции: Февр. 2012  


Помог: 353 раз(а)




ёлки-палки, про постфиксную запись я и не подумал )


-----
Чем больше узнаю, тем больше я не знаю.
 
 Top
Мелкий Супермодератор
Отправлено: 22 Апреля, 2013 - 09:40:20
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




За что очень цепляется взгляд:
Negaty пишет:
case '+' and '-': return 2;

Это работает, но не так, как вы думаете:
PHP:
скопировать код в буфер обмена
  1. var_dump(prior('('), prior('+'), prior('*'), prior('b'));


-----
PostgreSQL DBA
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Вопросы новичков »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB