Precedencia, 2 implementaciones

Precedencia de operadores en C++

El término Precedencia hace referencia al conjunto de reglas que definen el orden en que se evaluará una operación en una expresión que contenga dos o más operadores.

Nota: Para los siguientes expresiones de ejemplo, te sugiero que primero los realices mentalmente (o con una calculadora) y después compares los valores obtenidos, puedes encontrar diferencias interesantes.

Para deja clara la importancia de la precedencia de operadores consideremos la siguiente imagen:

Precedencia, 2 implementaciones
Precedencia, 2 implementaciones

Tenemos una misma operación, tenemos 2 resultados completamente distintos, ¿La razón? la forma en que está implementada la precedencia de operadores en cada calculadora.

El álgebra define un conjunto de reglas para evaluar expresiones, estas reglas de precedencia son universales e inmutables.

Sin embargo al implementar dicha precedencia en un sistema (software o hardware) pueden existir desviaciones en relación a la reglas algebraicas (como en el caso de la calculadora CASIO de la foto, las cuales pueden deberse a limitaciones técnicas, situaciones prácticas, en fin puede haber muchas razones, lo importante es revisar la documentación para saber como están implementadas las reglas de precedencia en un software o hardware en particular para poder implementar nuestras propias soluciones sin errores.

Antes de continuar, debemos elaborar nuestro propio programa para saber cual es “el resultado de C++” de la operación que se muestra en las calculadoras.

Nota: La expresión original enuncia una multiplicación implícita , dado que en C++ no podemos utilizar operadores implícitos debemos enunciarlos de forma explícita, por esta razón debemos modificar la expresión original al modo explícito Ambas operaciones son equivalentes.

// precedencia1.cpp
// Este programa ilustra la precendencia de operadores
// 2017, Por http://about.me/carlosgbr
// Versión 1
// Compilado en https://www.tutorialspoint.com/compile_cpp_online.php
#include <iostream>

using namespace std;

int main()
{
 float resultado = 0;
 
 //La expresión original es 6/2(2+1)
 resultado = 6/2*(2+1);
 cout << "Y el resultado al evaluar 6/2(2+1) en C++ es..." << resultado << endl; 
 
 return 0;
}

Con el programa anterior obtenemos la siguiente salida:

Precedencia de signos
Precedencia de signos

Si sabes álgebra, el resultado no debería tomarte por sorpresa.

Antes de revisar como está implementada la precedencia de operadores en C++, revisemos un segundo ejemplo:

¿Cuánto es 3^2-(-3^2)?
¿Cuánto es 3^2-(-3^2)?
// recedencia2.cpp
// Este programa ilustra la precedencia de operadores en C++
// 2017, Por http://about.me/carlosgbr
// Versión 1
// Compilado en https://www.tutorialspoint.com/compile_cpp_online.php

#include <iostream>
#include <math.h> //Nos permite utilizar la función pow()

using namespace std;

int main()
{
 float resultado = 0;
 
 //La expresión original es 3^2-(-3^2)= 0
 //Para elevar una base a una potencia utilizamos la función pow(base, potencia) de la librería math.h
 resultado = pow(3,2)-(-pow(3,2));
 cout << "Y el resultado al evaluar 3^2-(-3^2) en C++ es..." << resultado << endl; 
 
 return 0;
}

Nuevamente, a la luz del álgebra el resultado no requiere explicación.

La explicación, mejor dicho información, que si necesitamos como programadores, es la forma en que C++ implementa la precedencia de operadores, a siguiente tabla muestra los más comunes:

Precedencia de operadores de uso frecuente en C++

Descripción del operador Operador
Resolución de ámbito ::
Misma precedencia*
Incremento de prefijo ++
Decremento de prefijo ––
NOT lógico !
Negación unaria
Misma precedencia
Multiplicación *
División /
Módulo %
Misma precedencia
Adición +
Resta
Misma precedencia
Menor que <
Mayor que >
Menor o igual que <=
Mayor o igual que >=
Misma precedencia
Igualdad ==
Desigualdad !=
Misma precedencia*
Asignación =
Asignación y multiplicación *=
Asignación y división /=
Asignación y módulo %=
Asignación y suma +=
Asignación y resta –=
  1. La prioridad en precedencia disminuye de arriba hacia abajo
  2. Si un símbolo tiene la misma precedencia que otro símbolo en la misma expresión, se evaluará por regla general de izquierda a derecha, aunque hay grupos que operan de derecha a izquierda*
  3. La lista completa de precedencia la puedes consultar en el anexo III

La prioridad en precedencia disminuye de arriba hacia abajo.

Derivado de la lista de precedencia tenemos que en la expresión

9 * 2 - 2

Se evaluará primero la expresión 9 * 2, al resultado de esta operación, se le restarán 2, esto debido a que la multiplicación tiene mayo prioridad que la suma.

En la expresión

10 / 2 + 4 * 2

Tenemos 2 operadores de la misma prioridad (multiplicación y división) y otro de menor prioridad (la suma), en este caso el compilador lo que hace es que evalúa las operaciones de mayor prioridad de izquierda a derecha, primero se evalúa 9 / 2, después se evalúa 4 * 2 y finalmente se suman los 2 resultados anteriores.

En la expresión,

2 + 8 / 2 * 5 * 2 / 2 - 5

Primero se evalúa 8 / 2, al resultado se le multiplica 5, al resultado se multiplica 2, al resultado se divide 2, al resultado se le suma 2, al resultado se le resta 5.

Finalmente en la expresión

9 < 2 < !1

Se evalúa primero !1 en cual al negar al operando lo hace false (0), después se evalúa 9 < 2 (Verdadero, 1), después el resultado (1) < 2 el cual es verdadero (1) el cual se evalúa contra el resultado de !1 (0) lo que es false (0)

// operador_asignacion.cpp
// Este programa muestra el uso del operador de asignación
// 2017, Por http://about.me/carlosgbr
// Versión 1
// Compilado en https://www.tutorialspoint.com/compile_cpp_online.php
#include <iostream>
using namespace std;

int main()
{
 int resultado = 0;
 bool resp;
 
 resultado = 9 * 2 - 2; 
 cout << "9 * 2 - 2 = " << resultado << endl; 
 
 resultado = 10 / 2 + 4 * 2; 
 cout << "10 / 2 + 4 * 2 = " << resultado << endl; 
 
 resultado = 2 + 8 / 2 * 5 * 2 / 2 - 5; 
 cout << "2 + 8 / 2 * 5 * 2 / 2 - 5 = " << resultado << endl; 
 
 resp = 9 < 2 < !1; 
 cout << "9 < 2 < !1 = " << resp << endl; 


return 0;
}

A continuación puedes ver la salida que obtenemos al ejecutar estas instrucciones en C++

Como puedes apreciar desde el primer ejemplo de esta sección, los resultados se prestan a interpretación por parte de quien revisa un ejemplo, algunos dirán un resultado y lo justificarán con mejores o peores argumentos. Y siempre encontrarás a otra persona que “sepa más álgebra” de modo que en torno a una operación se llegan a armar discusiones aveces bastantes acaloradas buscando el resultado “correcto”. Para no complicarte la vida con interpretaciones, lo más inteligente es utilizar los símbolos agrupadores (Paréntesis) para definir de forma explícita la forma en que se debe evaluar una expresión eliminando cualquier ambigüedad.

Paréntesis

Los paréntesis se utilizan para mejorar la legibilidad en una expresión, pero sobre todo para controlar la forma en que una expresión se evalúa, modificando la prioridad predeterminada presente en la expresión. observa los siguientes ejemplos:

(2 + 8 / 2 * 5 * 2 / 2) - 5 = 17

(2 + 8 / 2 * 5 * 2) / 2 - 5 = 16

2 + (8 / 2 * 5 * 2 / 2 - 5) = 17

2 + 8 / (2 * 5 * 2 / 2 - 5) = 3.6

Como puedes observar, utilizar paréntesis fuerza la forma en que se evalúa la expresión, de este modo puedes evaluar las expresiones de forma clara y precisa, dejando de lado cualquier ambigüedad posible.

La conclusión que podemos sacar de todo esto es que en primer lugar tengas mucho cuidado con la prioridad de cada operador que utilices para que la expresión en donde lo utilices ofrezca el resultado que buscas, esto es particularmente cierto en expresiones complejas y como segundo como segunda consideración Recuerda que puedes utilizar paréntesis para definir la forma y el orden en que se evalúa una expresión, independientemente de la prioridad que tengan los operadores Pero por supuesto sin ignorarla

Aunque la prioridad de operadores es relativamente fácil de comprender, resulta conveniente que te sientas cómodo y hagas algunos ejercicios adicionales por tu cuenta, en donde se evalúen distintas expresiones, de modo que te sea intuitivo el porqué de un resultado, considera que todos los lenguajes de programación manejan este concepto de una forma más o menos similar. Incluso hojas de cálculo como Excel manejan también el concepto de precedencia o prioridad

 

Por Roberto C. González
Para Ethical Hack


¿Deseas aprender BIEN Seguridad Informática “desde el principio”? 

Aplicación de medidas para la implantación de la L.O.P.D. en las empresas

Obtendrás información ampliada y más recursos en comparación con el material que ofrecemos de forma gratuita, y material adicional, visita https://ehack.mx/portfolio-view/material-de-estudio-ceh-online/ para más información o ecríbenos a ceh@ehack.mx

Ethical hack
Ethical hack

 Fuente Imágenes:

“Precedencia, 2 implementaciones”: desde Facebook.com
“¿Cuánto es 3^2-(-3^2)?”: desde Facebook.com

“Todas las demás imágenes de esta sección”: by Nala Systems

Licencia Creative Commons
Precedencia de operadores por Roberto C. González se distribuye bajo una Licencia Creative Commons Atribución-NoComercial-CompartirIgual 4.0 Internacional.
Basada en una obra en http://ehack.info/cpp01/.
Permisos que vayan más allá de lo cubierto por esta licencia pueden encontrarse en https://about.me/carlosgbr.
Comentarios de Facebook

Leave a Reply

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *