Orden de operaciones aritméticas (PEMDAS) y su aplicación en lenguajes de programación.

Todo un clásico en las redes sociales es que alguien comparta la operación 5+4/3-1*2 y que se monte un gallinero tremendo en los comentarios con distintas soluciones. Esto se debe a que mucha gente no tiene claro cómo va la jerarquía de las operaciones y el orden de evaluación de las mismas.

Si hablamos de operaciones básicas, y de la mayoría de lenguajes de programación (Javascript, PHP, Python, Ruby, C,Visual Basic, Java…), nos regiremos por el orden de operaciones conocido por el acrónimo inglés PEMDAS, que en castellano podríamos traducir como PAPOMUDAS (PAréntesis, POtencias, MUltiplicación, División, Adición, Sustracción). En base a esto el orden de operaciones en lenguajes de programación como Python, PHP, Ruby o Javascript sería:

  1. Paréntesis
  2. Potencias y radicales
  3. Multiplicación, división, división entera y módulo.
  4. Suma y resta.

En este enlace puedes comprobar los resultados de distintas operaciones realizados en distintos lenguajes de programación. Puedes copiar los siguientes ejemplos para comprobar que el resultado es el mismo.

Aquí el código en Javascript:

var resultado = 5+4/3-1*2;
console.log(resultado);

Aquí el código en Python:

resultado = 5+4/3-1*2
print(resultado)

Aquí en Java:

public class Test {
  public static void main(String[] args){
    System.out.println(5.0+4.0/3.0-1.0*2.0);
  }
}

Y aquí en C:

void main(void) {
   double resultado;
   resultado = 5.0+4.0/3.0-1.0*2.0;
   printf("%f",resultado);
}

Como puedes comprobar, en todos el resultado es 4.333333 ya que todos usan el mismo orden para las operaciones.

Anuncios

Cálculo del logaritmo y logaritmo neperiano en Javascript.

Ayer me mandaban este chiste por Whatsapp:

Y como soy así de tocahuevos, que hasta llevo un reloj calculadora Casio, les mandé de vuelta el resultado del logaritmo neperiano de 1437. Y sí, estoy escribiendo esto para cuando me lo vuelvan a mandar, para contestar con este enlace, que me vale tanto para la sección de programación como para la de ciencia.

El elcálculo de logaritmos es la operación inversa a la exponenciación de la base del logaritmo. El desarrollo de calculadoras y ordenadores ha hecho que las tablas de logaritmos, que se usaban hace años para simplificar operaciones complejas, hayan perdido mucha importancia para los estudiantes de matemáticas en la actualidad. Este blog nos da una entrada muy intersante sobre el uso de los logaritmos.

La clase Math de Javascript tiene varias funciones para calcular un logaritmo. Para el logaritmo natural (logaritmo cuya base es el número e, un número irracional cuyo valor aproximado es 2,7182818284590452353602874713527):

//vamos a calcular el logaritmo de 5
var logaritmo = Math.log(5);

¿Y para obtener el logaritmo en base 10?

//vamos a calcular el logaritmo de 5
//pero con base decimal
var logaritmo = Math.log10(5);

¿Y para obtener el logaritmo en base 2?

//vamos a calcular el logaritmo de 5
//pero con base binaria
var logaritmo = Math.log2(5);

¿Y el logaritmo neperiano? Bueno, en lenguaje coloquial suele llamarse logaritmo neperiano al logaritmo natural, pero si nos ponemos precisos son dos conceptos disintos. El logaritmo neperiano, nombrado en honor del matemático John Napier, se calcularía con la fórmula -107*ln(x/-107):

//vamos a calcular el logaritmo neperiano
//de 5.
var logaritmo = Math.pow(-10,7)*Mat.log(5/Math.pow(-10,7))

Como puedes ver los logaritmos neperianos son esencialmente logaritmos naturales con la coma desplazada siete posiciones hacia la derecha y el signo invertido.

¿Qué es una función hash?

Ayer comentaba en Facebook que una cadena alfanumérica que aparecía en una noticia “parecía el resultado de alguna función hash” y hubo gente que me preguntó qué era eso de una función hash. Así que he pensado que lo mejor será contarlo por aquí que me puedo extender más.

Cifrado

Las funciones hash, también llamadas “digest” o “de resumen“, son algoritmos que calculan y devuelven una cadena de texto alfanumérica de longitud fija calculada a partir de un dato de entrada, que puede ser un texto o un fichero binario. Se trata de funciones unidireccionales, lo que quiere decir que aun teniendo el resultado y conociendo el algoritmo no debe ser posible revertir las operaciones para descifrar el dato de entrada.

Son también funciones determinísticas, siempre devuelven la misma salida para la misma entrada. Al ser resúmenes existe la posibilidad de que dos entradas totalmente distintas devuelvan el mismo resultado, es lo que se llama una “colisión“. Teóricamente es imposible crear una función hash sin colisiones, puesto que las posibilidades de entrada son infinitas pero las de salida están limitadas a la longitud de la cadena de resumen, por tanto a mayor logitud de respuesta menor posibilidad de colisión y mayor robustez para el algoritmo. Las colisiones son lo que facilita un tipo de ataque criptográfico llamado “Ataque de Cumpleaños” del que puedes leer en ese enlace.

Por ejemplo, si calculo el hash de la cadena “hola” con el algoritmo md5 el resultado será: 4d186321c1a7f0f354b297e8914ab240. En cambio si le paso la cadena “Hola“, con mayúscula, el resultado devuelto será: f688ae26e9cfa3ba6235477831d5122e.

¿Qué utilidad tiene esto? Bueno, no se trata de un algoritmo para cifrar un mensaje y poder descifrarlo luego, como pueda ser el caso de AES, no tiene el mismo propósito que la criptografía simétrica o asimétrica. Las funciones hash son útiles por ejemplo para almacenar contraseñas en una base de datos, ya que aunque alguien lograra acceder a ellas no podría descifrar cual es la contraseña original. Otro de sus principales usos es asegurar que un fichero no ha sido modificado durante el trayecto desde su envío: se calcula el hash antes de enviarlo, si al recibirlo lo volvemos a calcular y el resultado no es el mismo implica que alguien ha capturado (un ataque de intermediario o man in the middle) y modificado el fichero. Las funciones hash también se utilizan en los procesos de firma digital de documentos.

¿Cuales son los algoritmos de resumen más populares o más comunes? Te dejo una lista con sus enlaces a Wikipedia:

Diferencia entre muestra y población.

Población y Muestra son dos términos usados en estudios de estadística, similares y relacionados. Por dicha similitud tienden a ser confundidos, por lo que es importante que sepamos diferenciarlos para no tomar, literalmente, la parte por el todo.

La población, también llamada universo, es un conjunto de elementos sobre los que se realizan estudios y observaciones. Se trata de una variable o magnitud aleatoria con unas determinadas características comunes. Es, en resumen, el conjunto formado por todos los elementos a estudiar. Pero hay casos en los que el total de la población adquiere una magnitud demasiado extensa para ser estudiada. Por ejemplo, si queremos hacer un estudio sobre la salud cardiovascular en la Unión Europea no podemos pretender usa datos de todos los ciudadanos con historiales médicos.

La muestra es una selección abarcable de parte de una población para su estudio. Por definición, la muestra se siempre una parte de la población. Esta debe ser representativa, por lo que el método de selección debe ser adecuado (preferiblemente aleatorio) para evitar acabar teniendo un muestra sesgada que nos de un resultado irreal (decía un catedrático en estadística que un muestreo suficientemente torturado puede demostrar cualquier cosa). Siguiendo el ejemplo anterior, si hacemos el estudio sobre salud cardiovascular eligiendo solo a gente de entre 20 y 30 años y lo repetimos después con gente de más de 70, el resultado obtenido será radicalmente distinto.

Si la selección del muestreo es adecuada el resultado del estudio sobre una muestra será más preciso que al realizarlo sobre el total de la población, dado que trabajamos sobre un conjunto de datos más pequeño y esto nos permitirá minimizar errores.

En resumen: La población es el total de individuos o elementos que queremos estudiar y la muestra es una selección aleatoria de elementos de esa población que utilizaremos para trabajar de forma más precisa.

Diferencia entre media, mediana y moda

La media, la mediana y la moda son términos estadísticos que se usan para la comprensión de tendencias centrales cuando analizamos un conjunto de valores.

La media aritmética o promedio es especialmente útil cuando tratamos con distribuciones regulares. Se calcula mediante la suma de todos los valores observados dividida entre el número de observaciones. Pierde utilidad cuando se trata de distribuciones muy irregulares, con mucha diferencia. El ejemplo clásico de esto: si yo me como un pollo y tú no comes nada la media es que nos hemos comido medio pollo por cabeza.

La mediana es el valor numérico central de un conjunto de números, y es más útil cuando tratamos con distribuciones irregulares. Para su cálculo necesitamos ordenar toda la serie de valores de menor a mayor. Tras esto, en caso de que el número total de valores sea par, la mediana se calcula sacando el promedio de los dos valores centrales. En el caso de que sea una cantidad impar de valores la mediana será directamente el valor central.

Finalmente la moda es la incidencia más repetida en un conjunto de valores. Esto implica que puede haber más de una moda. Es útil cuando lo relevante es conocer el valor más común.

Veamos un ejemplo: imaginemos que tenemos un grupo de cinco amigas y vamos a calcular la media, mediana y moda de sus salarios anuales. Una cobra 12.000 euros, otra 15.000, otra 300.000 y hay dos que cobran 18.000.

La media sería el resultado de (12.000+15.000+300.000+18.000+18.000)/5, que es 72.600 euros. Como ves, al haber un valor tan alejado del resto dispara la media muchísimo.

Para la mediana vamos a ordenar los valores: 12.000|15.000|18.000|18.000|300.000. Al ser impar ya nos quedamos con el valor central, que sería 18.000 euros.

Finalmente para la moda miramos cual es el valor más repetido, que son también 18.000 euros ya que está dos veces en la lista.

Si crees que esto no es útil para el día a día piénsalo mejor, comprender bien estos conceptos nos permite abordar de forma más crítica muchas informaciones económicas que nos dan desde la prensa o desde los gobiernos.

Introducción al álgebra booleana: ¿Qué es?

El álgebra booleana es una estructura algebraica que esquematiza las operaciones lógicas, tomando su nombre de George Boole quien fue el primero en definirla como parte de un sistema lógico en 1847, en un intento de utilizar las técnicas algebraicas para tratar expresiones de la lógica proposicional.

El Álgebra de Boole es un conjunto “A”, provisto de dos operaciones binarias AND, OR, una operación unaria NOT y dos elementos 0 (Falso) y 1 (Verdadero), de forma que para todos los elementos a, b y c del conjunto A, se cumplen los siguientes axiomas:

Asociatividad:
a OR ( b OR c ) = ( a OR b ) OR c
a AND ( b AND c ) = ( a AND b ) AND c

Conmutatividad:
a OR b = b OR a
a AND b = b AND a

Absorción:
a OR (a AND b)=a
a AND (a OR b)=a

Distribuitividad:
a OR (b AND c)=(a OR b) AND (a OR c)
a AND (b OR c)=(a AND b) OR (a AND c)

Complementación:
a OR NOT a = 1
a AND NOT a = 0

Como en una computadora digital hay sólo dos posibilidades, usar el 0 o bien el 1 para representar el objeto más pequeño e indivisible, el álgebra booleana se convierte en una de las herramientas fundamentales de la computación y de la electrónica. Todos los datos se reducen finalmente a combinaciones de bits y los circuitos electrónicos permiten que estos recursos de almacenamiento se comuniquen entre sí. Un bit en una parte de un circuito se transmite a otra como voltaje. Por ello se necesitan dos niveles de voltaje: un voltaje alto que comunique el 1 y un voltaje bajo que comunique el 0. Fue Claude Shannon, en 1938, el primero en darle esta utilidad para simplificar circuitos conmutadores.

Operación AND.
La operación AND es exactamente igual a una multiplicación normal por lo cual sus reglas son las siguientes:

  1. Solamente si todas las entradas son 1 la salida será 1.
  2. Cuando una o más entradas sean 0 la salida será 0.

En el caso de una compuerta AND en un circuito electrónico esta opera en tal forma que su salida es ALTA sólo cuando todas sus entradas son ALTAS. En todos los otros casos la salida de la compuerta AND es BAJA.

Operación OR:
La operación OR es básicamente una suma y sus reglas son las siguientes:

  1. Produce un resultado de 1 cuando cualquiera de las variables de entrada es 1.
  2. Produce un resultado de 0 solo cuando todas las variables de entrada son 0.

En el caso de una compuerta OR opera en tal forma que su salida es ALTA si la entrada A, B o ambas están en un nivel lógico 1. La salida de la compuerta OR será BAJA si todas sus entradas están en el nivel lógico 0.

Operación NOT:
La operación NOT también se conoce como inversión o complementación, básicamente nos devuelve el valor complementario al que tengamos. Es decir, si A es igual a 0 entonces NOT A sería uno 1.

En el caso de un circuito electrónico NOT este siempre tiene una sola entrada y su nivel lógico de salida es contrario al nivel lógico de esta entrada.

SQL-Server: Calcular el descuento compuesto

Tras un mes de parón por temas varios volvemos con energía al blog. Vamos a dar por finalizado el capítulo dedicado a los descuentos y la aplicación de sus fórmulas en consultas de SQL-Server mirando el que nos queda, el descuento compuesto. Del descuento racional y del comercial ya hablamos en entradas pasadas.

El descuento compuesto es la operación inversa de la capitalización compuesta: si descontamos un capital utilizando el descuento compuesto, y el importe obtenido lo capitalizamos (capitalización compuesta) aplicando el mismo tipo de interés y plazo, obtenemos el importe inicial.

La fórmula para obtener el descuento sería la siguiente:

D = C0 * (1 – (1 + d) ^ -t )

Siendo C0 es el capital inicial en el momento t=0, d la tasa de descuento que se aplicará y t el tiempo que dura la inversión.

Para obtener el capital final la fórmula sería:

Cf = C0 * ( 1 + d ) ^ -t

Siendo C0 es el capital inicial en el momento t=0, d la tasa de descuento que se aplicará y t el tiempo que dura la inversión.

Entonces ¿cómo llevamos esto a una consulta SQL? Supongamos que, como en el ejemplo anterior, tenemos una tabla llamada TablaCreditos con los campos Valor (con el capital inicial en formato money), Descuento (en formato Numeric(5,2)) y Tiempo (en formato int). La consulta sería:

--Descuento
Select Valor * (1.00-POWER((1.00+Descuento),Tiempo)) as DescuentoCompuesto from TablaCreditos
--Capital final
Select Valor * POWER((1.00+Descuento),Tiempo) as CapitalFinal from TablaCreditos