[Закрыть]
 
popoff.donetsk.ua
Если мы хотим, чтобы что-то было в будущем, то менять нужно настоящее, без оглядки на то, что было в прошлом. /Popoff/
Начало | Новости | Статьи | Форум | Опросы | Карта сайта | Обо мне
popoff.donetsk.ua - Клуппы Yato - Программирование - Модули - a - a.calc
Я это делаю
Персональное меню
Голосование
Клуппы Yato Постоянный адрес этого вопроса
Деньги, но неинтересная работа и невозможность уделить время семье
Интересная работа, возможность саморазвиваться, но нищенский заработок
Ваш возраст (не обязательно)
Почему? (не обязательно)

Голосование закрыто.

Поиск по сайту
Реклама
Гинеколог, стоматолог, психотерапевт в Донецке
Статистика

a.calc

Постоянный адрес статьи

a.calc - Функция для вычисления значения формулы

При помощи этой функции можно вычислять простые формулы, содержащие в себе основные арифметические операции (+, -, *, /), скобки и переменные.

Переменные могут передаваться двумя способами.

$s_table - имя таблицы, которая содержит в себе имена и значения переменных. Имя переменной хранится в поле с именем s_file, а значение переменной - в поле с именем s_value.

$a_variable - массив, в котором ключ - это имя переменной, а значение - это значение переменной.

Для проверки правильноcти введенного арифметического выражения используется функция a_calc_valid.

Пример вызова функции:

Пусть, есть таблица t_variables:
s_file s_value
a 1
b 2

<?php echo a_calc('a-(b+c*d)+5','t_variables',array('c' => 3'd' => 4));
?>

Результат будет: 1-(2+3*4)+5 = -8.

Исходный текст модуля a.calc.

Постоянный адрес статьи
<?php // libs/a/a.calc.php
// (c) Yuri Popoff, Jun 2004, popoff.donetsk.ua
// A set of functions to calculate a formula
// See
//   http://popoff.donetsk.ua/text/work/libs/a/calc/
// for description

function debug_info($s)
{
  
trigger_error($s);
}

function 
_a_calc_operator(&$a_prg,&$a_op,$s_op,$i_priority)
{
  while((
$i=count($a_op))&&$a_op[$i-1][1]>=$i_priority)
  {
    
$a_prg[]=$a_op[$i-1][0];
    
array_pop($a_op);
  }
  
$a_op[]=array($s_op,$i_priority);
}

function 
_a_calc_br($s_value,$s_table,$a_variable,$a_used)
{
  
$s_value=str_replace(' ','',$s_value);
  
$a=preg_split('~([+*/()-])~',$s_value,-1,PREG_SPLIT_DELIM_CAPTURE);
  
$a_prg=array();
  
$a_op=array();
  
$i_level=0;
  
$s=0;
  
$i_state=2//0 - op, 1 - value, 2 - (, 3 - )
  
for($i=0;$i<count($a);$i++)
  {
    if(!
strlen($a[$i])) continue;
    switch(
$a[$i])
    {
      case 
'+':
      case 
'-':
      case 
'*':
      case 
'/':
        if(
$i_state==0||$i_state==2)
        {
          
debug_info($s_value.': operator after operator');
          return 
false;
        }
        
$i_state=0;
        
$s--;
        if(
$a[$i]=='+'||$a[$i]=='-')
          
_a_calc_operator($a_prg,$a_op,$a[$i],$i_level*2+0);
        else
          
_a_calc_operator($a_prg,$a_op,$a[$i],$i_level*2+1);
        break;
      case 
'(':
        if(
$i_state==1||$i_state==3)
        {
          
debug_info($s_value.': ( after value');
          return 
false;
        }
        
$i_state=2;
        
$i_level++;
        break;
      case 
')':
        if(
$i_state==0||$i_state==2)
        {
          
debug_info($s_value.': ) after operator');
          return 
false;
        }
        
$i_level--;
        
$i_state=3;
        if(
$i_level<0) return false;
        break;
      default:
        if(
$i_state==1||$i_state==3)
        {
          
debug_info($s_value.': value after value: '.$i_state.' '.$a[$i]);
          return 
false;
        }
        
$i_state=1;
        
$s++;
        
$a_prg[]=$a[$i];
    }
  }
  if(
$i_level)
  {
    
debug_info($s_value.' invalid bracket sequence');
    return 
false;
  }
  if(
$s!=1)
  {
    
debug_info($s_value.' invalid resulting stack size (1): '.$s);
    return 
false;
  }
  for(
$i=count($a_op)-1;$i>=0;$i--)
    
$a_prg[]=$a_op[$i][0];
  
$a_stack=array();
  
$i_stack=0;
  for(
$i=0;$i<count($a_prg);$i++)
  {
    switch(
$a_prg[$i])
    {
      case 
'+':
      case 
'-':
      case 
'*':
      case 
'/':
        if(
$i_stack<2)
        {
          
debug_info($s_value.': can not perform an operation. stack contains less then two operands.');
          return 
false;
        }
        
$i_stack--;
    }
    switch(
$a_prg[$i])
    {
      case 
'+':
        
$a_stack[$i_stack-1]+=$a_stack[$i_stack];
        break;
      case 
'-':
        
$a_stack[$i_stack-1]-=$a_stack[$i_stack];
        break;
      case 
'*':
        
$a_stack[$i_stack-1]*=$a_stack[$i_stack];
        break;
      case 
'/':
        
$a_stack[$i_stack-1]/=$a_stack[$i_stack];
        break;
      default:
        if(
is_numeric($a_prg[$i]))
        {
          
$a_stack[$i_stack++]=$a_prg[$i];
          break;
        }
        
$v=_a_calc_variable($a_prg[$i],$s_table,$a_variable,$a_used);
        if(
$v===false) return false;
        
$a_stack[$i_stack++]=$v;
    }
  }
  if(
$i_stack!=1)
  {
    
debug_info($s_value.' invalid resulting stack size (2)');
    return 
false;
  }
  return 
$a_stack[0];
}

function 
_a_calc_variable($s_variable,$s_table,$a_variable,$a_used)
{
  global 
$A_CALC;

  if(!empty(
$a_used[$s_variable]))
  {
    
debug_info($s_variable.': recursive variable reference');
    return 
false;
  }
  
$a_used[$s_variable]=true;
  if(isset(
$a_variable[$s_variable]))
  {
    if(
is_numeric($a_variable[$s_variable]))
      return 
$a_variable[$s_variable];
    return 
_a_calc_br($a_variable[$s_variable],$s_table,$a_variable,$a_used);
  }
  if(
$s_table)
  {
    if(isset(
$A_CALC[$s_table.'-'.$s_variable]))
      
$v=$A_CALC[$s_table.'-'.$s_variable];
    else
    {
      
$v=mysql_query_single("select s_value from ".$s_table." where s_file='".addslashes($s_variable)."'");
      
$A_CALC[$s_table.'-'.$s_variable]=$v;
    }
    if(
$v)
    {
      if(
is_numeric($v)) return $v;
      return 
_a_calc_br($v,$s_table,$a_variable,$a_used);
    }
  }
  
debug_info($s_variable.': undefined variable');
  return 
false;
}

function 
a_calc($s_value,$s_table=null,$a_variable=array())
{
  if(
is_numeric($s_value)) return $s_value;
  return 
_a_calc_br($s_value,$s_table,$a_variable,array());
}

// *** INITIALIZATION ***
global $A_CALC;
$A_CALC=array();

?>

a.calc.valid

Постоянный адрес статьи
<?php // libs/a/a.calc.valid.php
// (c) Yuri Popoff, Jun 2004, popoff.donetsk.ua
// A set of functions to verify if a formula is correct
// See
//   http://popoff.donetsk.ua/text/work/libs/a/calc/
// for description

include_once('a.calc.php');

function 
a_file_valid($s)
{
  if(empty(
$s)) return false;
  if(!
is_string($s)) return false;
  
$l=strlen($s);
  if(
$l>=255) return false;
  if(!
preg_match("/[0-9a-zA-Z_.-]{".$l."}/",$s)) return false;
  if(
$s[0]=='.'||$s[0]=='-'||$s[$l-1]=='.'||$s[$l-1]=='-') return false;
  if(
strpos('..',$s)!==false||strpos('--',$s)!==false) return false;
  return 
true;
}

function 
a_calc_valid($s_value,$is_variable=false)
{
  if(
is_numeric($s_value)) return true;

  
$s_value=str_replace(' ','',$s_value);
  
$a=preg_split('~([+*/()-])~',$s_value,-1,PREG_SPLIT_DELIM_CAPTURE);
  
$a_prg=array();
  
$a_op=array();
  
$i_level=0;
  
$s=0;
  
$i_state=2//0 - op, 1 - value, 2 - (, 3 - )
  
for($i=0;$i<count($a);$i++)
  {
    if(!
strlen($a[$i])) continue;
    switch(
$a[$i])
    {
      case 
'+':
      case 
'-':
      case 
'*':
      case 
'/':
        if(
$i_state==0||$i_state==2)
        {
          
debug_info($s_value.': operator after operator');
          return 
false;
        }
        
$i_state=0;
        
$s--;
        if(
$a[$i]=='+'||$a[$i]=='-')
          
_a_calc_operator($a_prg,$a_op,$a[$i],$i_level*2+0);
        else
          
_a_calc_operator($a_prg,$a_op,$a[$i],$i_level*2+1);
        break;
      case 
'(':
        if(
$i_state==1||$i_state==3)
        {
          
debug_info($s_value.': ( after value');
          return 
false;
        }
        
$i_state=2;
        
$i_level++;
        break;
      case 
')':
        if(
$i_state==0||$i_state==2)
        {
          
debug_info($s_value.': ) after operator');
          return 
false;
        }
        
$i_level--;
        
$i_state=3;
        if(
$i_level<0)
        {
          
debug_info($s_value.': too many closing brackets');
          return 
false;
        }
        break;
      default:
        if(
$i_state==1||$i_state==3)
        {
          
debug_info($s_value.': value after value: '.$i_state.' '.$a[$i]);
          return 
false;
        }
        
$i_state=1;
        
$s++;
        
$a_prg[]=$a[$i];
    }
  }
  if(
$i_level)
  {
    
debug_info($s_value.' invalid bracket sequence');
    return 
false;
  }
  if(
$s!=1)
  {
    
debug_info($s_value.' invalid resulting stack size (1)');
    return 
false;
  }
  for(
$i=count($a_op)-1;$i>=0;$i--)
    
$a_prg[]=$a_op[$i][0];
  
$i_stack=0;
  for(
$i=0;$i<count($a_prg);$i++)
  {
    switch(
$a_prg[$i])
    {
      case 
'+':
      case 
'-':
      case 
'*':
      case 
'/':
        if(
$i_stack<2)
        {
          
debug_info($s_value.': can not perform an operation. stack contains less then two operands.');
          return 
false;
        }
        
$i_stack--;
    }
    switch(
$a_prg[$i])
    {
      case 
'+':
      case 
'-':
      case 
'*':
      case 
'/':
        break;
      default:
        
$i_stack++;
        if(
is_numeric($a_prg[$i])) break;
        if(!
$is_variable)
        {
          
debug_info($s_value.': variables not allowed.');
          return 
false;
        }
        if(!
a_file_valid($a_prg[$i]))
        {
          
debug_info($s_variable.': invalid variable name');
          return 
false;
        }
    }
  }
  if(
$i_stack!=1)
  {
    
debug_info($s_value.' invalid resulting stack size (2)');
    return 
false;
  }
  return 
true;
}

?>

Последняя модификация: 02.03.06 13:01