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.

Cómo hacer un Hello World! en distintos lenguajes de programación.

El Hello World es un ejercicio básico de programación. Casi en cualquier lenguaje de programación que estudies empezarás en la primera lección programando uno. Aquí te dejo diversos ejemplos en distintos lenguajes
, lo que además te permitirá ver algunas de las pequeñas diferencias que hay entre ellos.

ASP:

Response.Write "Hello World!" 

Script de Bash:

#!/bin/bash
echo "Hello, World!" 

C:

#include 
main(){
  printf ("Hello World!\n");
}

C++:

#include 
using namespace std;
void main(){
  cout << "Hello World!" << endl;
}

C#:

using System;
namespace HelloWorld
{
    class Hello 
    {
        static void Main() 
        {
            Console.WriteLine("Hello World!");            
        }
    }
}

Java:

class hellWorldJava{
  public static void main(String args[]){
    System.out.println("Hello World!");
  }
}

Javascript:

window.alert( 'Hello, world!' );

Objective C:

#import 

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
    }
    return 0;
}

Perl:

#!/usr/bin/perl
print “Hello World.\n”;

PHP:

echo "Hello World!";

Script de Powershell:

$strString = "Hello World"
write-host $strString

Python:

print "Hello, World!"

R:

print("Hello World!", quote = FALSE)

Ruby:

puts 'Hello world'

Instalar el JDK8 y JDK9 de Java en Ubuntu, Mint o Debian

Si en su día ya habíamos visto en este blog cómo hacerlo con la versión 7, el procedimiento para instalar Java 8 o Java 9 es, básicamente, el mismo:

El primer paso, añadir el repositorio, es común:

#Añadir el repositorio
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update

Con él ya añadido, instalamos la versión 8:

#Buscar y descargar
#los paquetes de java 8
$ apt-cache search oracle-java8
$ sudo apt-get install oracle-java8-installer

Para la versión 9:

#Buscar y descargar
#los paquetes de java 9
$ apt-cache search oracle-java9
$ sudo apt-get install oracle-java9-installer

¿Y cómo definimos cual será la versión por defecto si tenemos las dos instaladas?

#Así por defecto la 9:
$ sudo apt-get install oracle-java9-set-default
#Así por defecto la 8:
$ sudo apt-get install oracle-java8-set-default

Instalar decompilador de Java en Ubuntu: JD-GUI

¿Necesitas un software que te permita decompilar una clase Java en tu Ubuntu? Pues hoy os hablo de JD-Project, un proyecto OpenSource que nos permitirá destripar esos ficheros en nuestro equipo. Si queréis pegarle un ojo al código ahí tenéis la página de GitHub.

En la web oficial del proyecto podemos ver que nos ofrecen varios “sabores”: JD-GUI, como aplicación independiente, JD-Eclipse como plugin para el popular entorno de desarrollo y JD-IntelliJ para el IDE IntelliJ. Yo para hacer la prueba me descargué JD-GUI, que luce tal como en las fotos:

JD-GUI Windows
Así luce JD-GUI en Windows
JD-GUI xubutu
Y este es el JD-GUI en un Xubuntu 16-04 LTS

En mi caso descargué el paquete .deb para derivados de Debian y no tuve más que hacer doble click para instalar. Eso sí, la primera llegó en la frente: ejecuto y falla. ¿por qué? Pues básicamente porque no tenía Java instalado en el equipo de la prueba… un despistillo por usar un equipo recién instalado. Instalo Oracle Java 8… y por algún motivo la instalación del mismo se carga el JD-GUI. Así que otra vez a instalar el .deb de JD-GUI. Pero tras todo esto el programa ya ha funcionado como la seda. Así que ya podéis disfrutar de esta cómoda herramienta.

Incluir java en el PATH de Windows

Aunque no siempre es necesario, a veces nos tocará modificar la variable PATH de Windows y añadir la ubicación de Java para utilizar algún software concreto.

Todavía no he tenido que hacerlo en Windows 10, pero os comento cómo va la coas en Windows 8 y Windows 7. Voy a omitir XP porque al estar descontinuado no es cosa de darle soporte (de hecho la propia Oracle no asegura el funcionamiento de las últimas versiones de Java, aunque con el SP3 funciona de momento).

Vamos con las instrucciones para Windows 7:

  1. Abrimos el menú de inicio y hacemos click derecho sobre Equipo y, en el menú contextual seleccionamos Propiedades del Sistema.
  2. Hacemos click en Configuración avanzada del sistema -> Opciones avanzadas.
  3. Hacemos click en Variables de entorno, allí en Variables del sistema, buscamos PATH y hacemos click en él.
  4. En la ventana Editar, modificamos PATH agregando la ubicación de java en nuestro equipo al valor de PATH.

Y ahora las instrucciones para Windows 8:

  1. Hacemos click en Búsqueda y buscamos Panel de control
  2. Ahí hacemos click en Panel de control -> Sistema -> Opciones avanzadas
  3. Ahí vamos a Variables de entorno, y ahí en Variables del sistema, buscamos PATH y hacemos click en él.
  4. En la ventana Editar, modificamos PATH agregando la ubicación de java en nuestro equipo al valor de PATH.

En cuanto lo tenga que hacer en Windows 10 os lo agrego por aquí.

Clase para prevenir ataques XSS en Java

Buscando información para aumentar la seguridad de una aplicación web basada en Java me encontré con esta clase para filtrar los posibles ataques XSS en la web de un veterano ingeniero llamado Ricardo Zuasti.

Su solución propone dos clases. La primera, que copio de su entrada original a continuación, lo que hace es filtrar las peticiones HTTP para que sean filtradas por la clase especializada creada para eso:

public class XSSFilter implements Filter {
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
 
    @Override
    public void destroy() {
    }
 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response);
    }
 
}

Tras esto propone la siguiente clase para realizar el filtrado. Esta clase sobreescribe los métodos getParameterValues(), getParameter() y getHeader() y utiliza una serie de patrones para evitar la entrada de código malicioso en tu web. El método stripXSS() es el que realiza la labor de filtrado.

import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
 
public class XSSRequestWrapper extends HttpServletRequestWrapper {
 
    private static Pattern[] patterns = new Pattern[]{
        // Script fragments
        Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE),
        // src='...'
        Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        // lonely script tags
        Pattern.compile("</script>", Pattern.CASE_INSENSITIVE),
        Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        // eval(...)
        Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        // expression(...)
        Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        // javascript:...
        Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE),
        // vbscript:...
        Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE),
        // onload(...)=...
        Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL)
    };
 
    public XSSRequestWrapper(HttpServletRequest servletRequest) {
        super(servletRequest);
    }
 
    @Override
    public String[] getParameterValues(String parameter) {
        String[] values = super.getParameterValues(parameter);
 
        if (values == null) {
            return null;
        }
 
        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0; i < count; i++) {
            encodedValues[i] = stripXSS(values[i]);
        }
 
        return encodedValues;
    }
 
    @Override
    public String getParameter(String parameter) {
        String value = super.getParameter(parameter);
 
        return stripXSS(value);
    }
 
    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        return stripXSS(value);
    }
 
    private String stripXSS(String value) {
        if (value != null) {
            // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
            // avoid encoded attacks.
            // value = ESAPI.encoder().canonicalize(value);
 
            // Avoid null characters
            value = value.replaceAll("\0", "");
 
            // Remove all sections that match a pattern
            for (Pattern scriptPattern : patterns){
                value = scriptPattern.matcher(value).replaceAll("");
            }
        }
        return value;
    }
}

Entre las recomendaciones que da en el artículo original está la de configurar este filtro como el primero en tu web.xml y también, en referencia al código que aparece comentado en la segunda clase, echarle un ojo a la librería ESAPI, que nos proporciona diversas soluciones de seguridad.

Desde aquí sólo me queda enviarle mi agradecimiento por su trabajo al señor Zuasti y animarle a recuperar su blog, que tiene material interesante pero hace tiempo que no actualiza.

El operador ternario ?: en Java

Seguramente hayas visto en algún ejemplo de código usar el símbolo de interrogación como un operador. Y te preguntarás ¿esto cómo va?. La idea es que más o menos funciona como un condicional if/else devolviendo un valor según una condición se cumpla o no. La sintaxis sería expresiónAEvaluar?valorADevolverSiCierto:valorADevolverSiFalso;

Y como ejemplo práctico, el siguiente código:

/*
Comprobamos si x es mayor que y. 
En caso afirmativo nuestra variable vale x,
y en caso negativo y.
*/
variable=(x>y)?x:y;
/*la alternativa al operador ternario, usando if/else sería*/
if(x>y){
  variable = x;
}else{
  variable = y;
}

Dicho operador existe, con algunas variantes en su sintaxis, también en PHP, C, C++, Python, Perl y aunque en VB.NET no existe sí disponéis de la función IIF cuyo funcionamiento es similar. Como puedes ver te permitirá ahorrar líneas de código y tener un código más elegante.

Java/JSP: al enviar formulario por método POST los caracteres UTF-8 no aparecen bien representados

Me encontraba esta mañana trabajando sobre un proyecto desarrollado en Java haciendo uso de páginas JSP para las vistas, y me encontré con que al enviar un formulario no se insertaban bien en la base de datos los caracteres acentuados y las ñ, apareciendo otros extraños en su lugar. No era la primera vez que veía esto, era evidente que había un problema de codificación.

Lo primero fue comprobar que todas las páginas tuvieran definida en su cabecera la codificación adecuada:

<%@page contentType="text/html" pageEncoding="UTF-8"%>

Tras ver que eso estaba correctísimo, se me ocurre aplicar al principio del código, antes de recoger los resultados, la siguiente función:

request.setCharacterEncoding("UTF-8");

Y parecía que funcionaba, pero no. En principio en la mayoría de los casos eso soluciona el problema, pero a veces el Tomcat es puñetero (en mi caso estaba usando este servidor) y en algunas casuísticas decide que sigue cascando. Así que seguí buceando, y me encontré con que el problema está en que por defecto Tomcat interpreta los datos recibidos por POST como ISO-8859-1. Y había por medio un servlet funcionando como filtro que me escarallaba todo haciendo inútil el consejo anterior. Total, que fui a estudiarme la configuración del Tomcat, a ver si lo arreglaba definitivamente. Y así fue.

Lo primero es ir a la configuración de Tomcat y editar el archivo Server.xml, buscas allí el elemento Connector y en el valor de URIEncoding pones “UTF-8”. Tras esto te vas a la carpeta WEB-INF de tu aplicación y allí editas web.xml, pegando este filtro antes que ningún otro:

  <filter>
    <filter-name>Character Encoding Filter</filter-name>
    <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>Character Encoding Filter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

Un último punto: ojito a servlets que puedan funcionar como filtros intermedios antes de llegar a vuestra página jsp, a librerías de generación de contenidos o a frameworks varios, que igual tenéis que configurarlos también (cada proyecto es un mundo, pero por ejemplo con Velocity o Freemarker tendríais que configurarlos para UTF-8).

Calculando la distancia entre dos coordenadas en Java

Si no hace mucho os comenté por aquí cómo calcular la distancia entre dos puntos dadas sus coordenadas en MySQL (en ese artículo tenéis todo el tema del algoritmo para el cálculo más desarrollado, aquí vamos al grano), hoy vamos a ver cómo hacer una función que nos haga esta operación con Java.

La función recibe cuatro parámetros: las latitudes y longitudes de ambos puntos. Y devuelve un double con la distancia como resultado

public static double distanciaCoord(double lat1, double lng1, double lat2, double lng2) {  
        //double radioTierra = 3958.75;//en millas  
        double radioTierra = 6371;//en kilómetros  
        double dLat = Math.toRadians(lat2 - lat1);  
        double dLng = Math.toRadians(lng2 - lng1);  
        double sindLat = Math.sin(dLat / 2);  
        double sindLng = Math.sin(dLng / 2);  
        double va1 = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)  
                * Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));  
        double va2 = 2 * Math.atan2(Math.sqrt(va1), Math.sqrt(1 - va1));  
        double distancia = radioTierra * va2;  
  
        return distancia;  
    }  

Conversión de boolean a int en Java

Entradita rápida y simple. ¿Tienes una variable con un booleano y necesitas convertirla en un entero? No es habitual, pero por ejemplo hoy me veía en esa tesitura con una vista en JSP. ¿Cual es la mejor forma en Java, la más eficiente y corta, de convertir un boolean en un entero? Pues la siguiente:

/*Supongamos una variable boolean llamada
miBooleano*/

int miEntero = miBooleano ? 1 : 0;

/*devuelve 1 si es true y 0 si es false*/