Autor Tema: Ejecutar operaciones a partir de un texto  (Leído 1163 veces)

Desconectado westwest

  • PHPero Master
  • ******
  • Mensajes: 2.837
  • Karma: 104
  • Sexo: Masculino
    • Ver Perfil
Ejecutar operaciones a partir de un texto
« en: 20 de Abril de 2010, 20:49:32 pm »
Ayer necesitaba ejecutar una ecuación guardada en la base de datos.
Como $var = $fetch['ecuacion']; lo almacena como simple texto, he recurrido a eval poniendo:

eval("\$return=" $equation ";");
echo 
$return;
// Si hicieramos $equation = "2*2+45"; imprimiria 49...

Hasta ahí bien, pero el problema llegó cuando quise hacer potencias, para hacerlas yo uso ^ (por la calculadora, por lo que 23 sería 2^3.
Pero PHP requiere usar pow(), así que me estrujé un poco la cabeza y saqué esta función, tal vez muy mejorable, y que funciona perfectamente.

function parseEquation($eq) {
// IPER FUNSION POR WESTWEST :D
	

                
$rest_eq $eq;
	
$prev_eq = '';
	
$pos strpos($rest_eq, '^');
	
while(
$pos !== false) {
	
	
settype($rest_eq, 'string');
	
	
$prev 0;
	
	
$array = array('(', '+', '-', '*', '/');
	
	
$addp 0;
	
	
foreach(
$array as $operator) {
	
	
	
$op strrpos(substr($rest_eq0$pos), $operator);
	
	
	
if(
$op !== false && $op >= $prev) {
	
	
	
	
$prev $op;
	
	
	
	
$addp 1;
	
	
	
}
	
	
}
	
	
$prev += $addp;
	
	
$next strlen($rest_eq)-1;
	
	
$array = array(')', '+', '-', '*', '/', '^');
	
	
$addp 0;
	
	
foreach(
$array as $operator) {
	
	
	
$op strpos(substr($rest_eq$pos+1), $operator);
	
	
	
if(
$op !== false && $op $next) {
	
	
	
	
$next $op;
	
	
	
	
$addp $pos;
	
	
	
}
	
	
}
	
	
$next += $addp;
	
	
$prev_eq .= substr($rest_eq0$prev).'pow('.substr($rest_eq, $prev, ($pos-$prev)).', '.substr($rest_eq, $pos+1, ($next-$pos)).')';
	
	
$rest_eq substr($rest_eq$next+1);
	
	
$pos strpos($rest_eq, '^');
	
}
	
$eq $prev_eq.$rest_eq;
	

	
eval(
"\$return=" $eq ";");
	

	
return 
round($return);
}


Explico un poco por encima, así de paso sirve de tutorial.
Primero con strpos determino donde hay un ^, esto devuelve false si no encuentra, así que el while se eecutará mientras haya alguno (notad que es !==, no !=).
Primero, con un foreach obtengo la mayor posición de un caracter que delimite a los números, ya que al lado irá "pow(", despues hago lo mismo pero tras el ^, y busco el primero.

El $addp es para que cuadre todo.
Despues "corto" la cadena y la monto en $prev_eq, en $rest_eq, la cadena que se analiza pongo lo que queda y, si es necesario, vuelve a empezar.

Luego lo paso por eval, lo redondeo y devuelvo.

Funciones:
eval
strpos
strrpos

No tiene una utilidad general, pero tal vez le sirva a alguien.

Salu2!
« Última modificación: 20 de Abril de 2010, 21:05:40 pm por westwest »

Comunidad PHPeros

Ejecutar operaciones a partir de un texto
« en: 20 de Abril de 2010, 20:49:32 pm »

Desconectado Warlox

  • Moderadores PHP
  • PHPero Master
  • ****
  • Mensajes: 1.278
  • Karma: 77
  • Sexo: Masculino
  • A veces hay que aprender a correr antes de caminar
    • Ver Perfil
    • Página personal
Re:Ejecutar operaciones a partir de un texto
« Respuesta #1 en: 20 de Abril de 2010, 21:00:53 pm »
No te entendí nada pero igual se ve útil. K+
- Moderador de PHP


Desconectado westwest

  • PHPero Master
  • ******
  • Mensajes: 2.837
  • Karma: 104
  • Sexo: Masculino
    • Ver Perfil
Re:Ejecutar operaciones a partir de un texto
« Respuesta #2 en: 20 de Abril de 2010, 21:06:59 pm »
No te entendí nada pero igual se ve útil. K+
Dificil veo que sin entender qué es veas útil :/

Desconectado Siquillote

  • PHPero Master
  • ******
  • Mensajes: 4.229
  • Karma: 179
  • Sexo: Masculino
    • Ver Perfil
Re:Ejecutar operaciones a partir de un texto
« Respuesta #3 en: 21 de Abril de 2010, 14:07:20 pm »

Vale, creo que algo he entendí. Eval se usa para aplicar operaciones matematicas sin que este de error
¿No es así?. Por ejemplo :

<?php
$ecuacion 
2*3+4+4
eval("\$valor=".$ecuacion.";");
echo 
$valor;
?>


Pero no entiendo lo siguiente : ¿Para que esta la \ antes de la variable valor? ¿Es prescindible?.

#Fdo. Physlet

Desconectado westwest

  • PHPero Master
  • ******
  • Mensajes: 2.837
  • Karma: 104
  • Sexo: Masculino
    • Ver Perfil
Re:Ejecutar operaciones a partir de un texto
« Respuesta #4 en: 21 de Abril de 2010, 15:25:45 pm »
Vale, creo que algo he entendí. Eval se usa para aplicar operaciones matematicas sin que este de error
¿No es así?. Por ejemplo :

<?php
$ecuacion 
2*3+4+4
eval("\$valor=".$ecuacion.";");
echo 
$valor;
?>


Pero no entiendo lo siguiente : ¿Para que esta la \ antes de la variable valor? ¿Es prescindible?.
Para que sea útil debes poner $ecuacion = "2*3+4+4"; para que sea string, si no no tiene sentido...

La \ es para escapar el $, si no pondría la variable $valor ahí

Desconectado Siquillote

  • PHPero Master
  • ******
  • Mensajes: 4.229
  • Karma: 179
  • Sexo: Masculino
    • Ver Perfil
Re:Ejecutar operaciones a partir de un texto
« Respuesta #5 en: 21 de Abril de 2010, 15:28:51 pm »

Ahhh vale vale ahora ya lo entiendo. Pues parece que no pero esta función es muy útil. Gracias west
+1

#Fdo. Physlet

Desconectado javipilo

  • PHPero Experto
  • *****
  • Mensajes: 975
  • Karma: 31
  • Sexo: Masculino
    • Ver Perfil
Re:Ejecutar operaciones a partir de un texto
« Respuesta #6 en: 21 de Abril de 2010, 17:05:16 pm »
Entonces es como una calculadora normal pones directamente en el text 2+2 y te lo suma no?

Saludos :)

Desconectado westwest

  • PHPero Master
  • ******
  • Mensajes: 2.837
  • Karma: 104
  • Sexo: Masculino
    • Ver Perfil
Re:Ejecutar operaciones a partir de un texto
« Respuesta #7 en: 21 de Abril de 2010, 20:08:48 pm »
Entonces es como una calculadora normal pones directamente en el text 2+2 y te lo suma no?

Saludos :)
Sí, podría ser

Desconectado javipilo

  • PHPero Experto
  • *****
  • Mensajes: 975
  • Karma: 31
  • Sexo: Masculino
    • Ver Perfil
Re:Ejecutar operaciones a partir de un texto
« Respuesta #8 en: 21 de Abril de 2010, 20:57:07 pm »
Pues está muy chulo :)

Conectado naveda

  • Administrador General
  • PHPero Master
  • *****
  • Mensajes: 2.282
  • Karma: 165
  • Sexo: Masculino
    • Ver Perfil
    • naveda.me
Re:Ejecutar operaciones a partir de un texto
« Respuesta #9 en: 21 de Abril de 2010, 23:57:40 pm »
Esta bien porque usa practicamente de todo :D
Eso si, con expresiones regulares podría quedarte todo en una o dos lineas :D
Por favor, leete las Normas


Desconectado marco811

  • PHPero Avanzado
  • ****
  • Mensajes: 306
  • Karma: 16
  • Sexo: Masculino
  • ¡¡Hola mundo!!
    • Ver Perfil
    • Personalidad Web
Re:Ejecutar operaciones a partir de un texto
« Respuesta #10 en: 22 de Abril de 2010, 08:09:32 am »
Esta bien porque usa practicamente de todo :D
Eso si, con expresiones regulares podría quedarte todo en una o dos lineas :D

Exacto, permitiendo solo el uso de los operadores logicos (+,-,*,/) y numeros y listo :)

Conectado naveda

  • Administrador General
  • PHPero Master
  • *****
  • Mensajes: 2.282
  • Karma: 165
  • Sexo: Masculino
    • Ver Perfil
    • naveda.me
Re:Ejecutar operaciones a partir de un texto
« Respuesta #11 en: 22 de Abril de 2010, 13:01:08 pm »
Bueno, en realidad me refiero a que con preg_replace() podría hacer una búsqueda del carácter ^ seguido por numero/s y reemplazarlo por Pow(numero/s).
Por favor, leete las Normas


Desconectado westwest

  • PHPero Master
  • ******
  • Mensajes: 2.837
  • Karma: 104
  • Sexo: Masculino
    • Ver Perfil
Re:Ejecutar operaciones a partir de un texto
« Respuesta #12 en: 22 de Abril de 2010, 15:00:40 pm »
Bueno, en realidad me refiero a que con preg_replace() podría hacer una búsqueda del carácter ^ seguido por numero/s y reemplazarlo por Pow(numero/s).
Tenías toda la razón! Mira que me he complicado la vida! Me he puesto a pensar y he sacado esto:

$eq 
"2*2^2+2";
$eq preg_replace(&#39;/(^|\(|\*|\+|\\|-)([0-9]+)\^([0-9]+)(\)|\*|\+|\\|-|\^|$)/&#39;, &#39;\\1pow(\\2, \\3)\\4&#39;, $eq);
eval("\$return=" $eq ";" );
echo 
round($return);


Bastante más eficiente xD,  voy a ver si hago las raices cuadradas, y edito el post ;)
« Última modificación: 22 de Abril de 2010, 15:29:21 pm por westwest »

Desconectado javipilo

  • PHPero Experto
  • *****
  • Mensajes: 975
  • Karma: 31
  • Sexo: Masculino
    • Ver Perfil
Re:Ejecutar operaciones a partir de un texto
« Respuesta #13 en: 22 de Abril de 2010, 19:51:31 pm »
Mira xD:
Código: [Seleccionar]
<form method="POST">
<input type="text" name="nums">
<input type="submit" value="Calcular">
</form>
<?php
if ($_POST[&#39;nums&#39;])
{
$eq $_POST[&#39;nums&#39;];
$eq str_replace("x""*"$eq);
$letras = array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","ñ","o","p","q","r","s","t","u","v","w","x","y","z");
$eq str_replace($letras""$eq);
if ($eq !== "")
{
$eq preg_replace(&#39;/(^|\(|\*|\+|\\|-)([0-9]+)\^([0-9]+)(\)|\*|\+|\\|-|\^|$)/&#39;, &#39;\\1pow(\\2, \\3)\\4&#39;, $eq);
eval("\$return=" $eq ";" );
echo $return;
}
}
?>


y para raizes:
Código: [Seleccionar]
<form method="POST">
<input type="text" name="nums">
<input type="submit" value="Calcular">
</form>
<?php
if ($_POST[&#39;nums&#39;])
{
$eq $_POST[&#39;nums&#39;];
$eq str_replace("raiz="$raiz$eq);
$eq str_replace("x""*"$eq);
if ($eq !== "")
{
$eq preg_replace(&#39;/(^|\(|\*|\+|\\|-)([0-9]+)\^([0-9]+)(\)|\*|\+|\\|-|\^|$)/&#39;, &#39;\\1pow(\\2, \\3)\\4&#39;, $eq);
eval("\$return=" $eq ";" );
echo $return;
}
}
?>


y en el form poner sqrt(numero) o para pontencias pow(numero) etc...
Aquí más información
http://www.rinconastur.net/php/php17.php
« Última modificación: 22 de Abril de 2010, 20:17:07 pm por javipilo »

Desconectado westwest

  • PHPero Master
  • ******
  • Mensajes: 2.837
  • Karma: 104
  • Sexo: Masculino
    • Ver Perfil
Re:Ejecutar operaciones a partir de un texto
« Respuesta #14 en: 22 de Abril de 2010, 21:44:07 pm »
El de raiz no tiene definida $raiz ni cambiado el preg_replace... :S

Hice lo de las raices, pero ando pensando como poner a los 2 en la misma ecuación, porque al poner V9^2 me devuelve sqrt(9)^2 y no va...

PD: Para las raices yo uso VNUMERO

Por cierto, sigo reduciendo las regulares xD Todo es mejorable!

$eq 
preg_replace(&#39;/([0-9]+)\^([0-9]+)/&#39;, &#39;pow(\\1, \\2)&#39;, $eq);
$eq preg_replace(&#39;/v([0-9]+)/i&#39;, &#39;sqrt(\\1)&#39;, $eq);
	


tengo que pensar...

Pfff y lo arreglé xD Ahora pueden usarse las 2 cosas

$eq 
preg_replace(&#39;/([0-9]+)\^([0-9]+)/&#39;, &#39;pow(\\1, \\2)&#39;, $eq);
$eq preg_replace(&#39;/v([0-9]+|pow\([0-9]+, [0-9]+\))/i&#39;, &#39;sqrt(\\1)&#39;, $eq);

Y como añadido, PHP no admite poner 2x, que es 2*x, así que así lo podríamos usar sin complicarnos la vida:

$eq 
preg_replace(&#39;/([0-9]+)([a-z]+)/i&#39;, &#39;\\1*\\2&#39;, $eq);

Sobra decir, que habría que sustituir las letras despues de aplicar esto.
« Última modificación: 22 de Abril de 2010, 22:46:53 pm por westwest »