Un algoritmo de generación de números pseudoaleatorios

números aleatorios

En la nota a pie del artículo La privacidad no existe citaba un artículo de la Wikipedia acerca de cómo generar números aleatorios mediante software. En esta entrada voy a poner un ejemplo sencillo desarrollado en Python. Obviamente Python tiene sus propias funciones para ello, pero nada nos impide desarrollar nuestra propia función.

En primer lugar veamos la teoría que hay detrás. Estos algoritmos lo que realmente generan son números pseudoaleatorios porque usan procedimientos sistemáticos. El método más empleado es el de congruencia lineal. Se eligen cuatro números enteros: un módulo m, un multiplicador a, el incremento c y la semilla x0 Estos números deben ser números enteros positivos mayores de 0. El artículo de la Wikipedia también impone que  a, c y x0 deben ser menores que m pero no encuentro ninguna razón para ello. De hecho, al final el artículo entra en contradicción al afirmar que el estándar POSIX para C define a = 1103515245 y m = 32768 Con lo que a > m

Una semilla válida la podemos obtener del reloj interno de la CPU: el RTC. En el ejemplo usaré el método time() de la librería time. Éste nos da el tiempo que ha pasado desde el tiempo Unix: el 1 de Enero de 1970. Como se puede ver, devuelve un número en coma flotante:

>>> time.time()
1487416084.126488

Como necesitamos un entero lo convertimos, el número de segundos será suficiente para el ejemplo. Sigue leyendo

La operación módulo en teoría de números y cómo la implementan diferentes lenguajes

En informática, la operación módulo, dados dos números, D el dividendo y d el divisor, nos da el resto r de la división entera de D por d, siendo d≠0 y |r|<|d|. Aunque no parece gran cosa, aun menos teniendo en cuenta que hace décadas que las CPUs incorporan coprocesadores matemáticos capaces de hacer a gran velocidad operaciones aparentemente más relevantes como raíces o logaritmos, la realidad es que es una operación fundamental en informática: Desde la generación de tablas de hash y números aleatorios hasta la criptografía, la generación de checksums y el álgebra computacional.

Veamos como Python resuelve esta operación. Abrimos la consola de Python y mediante el operador % le pedimos el módulo con D=27 y d=13:

>>> 27%13
 1

Así es: 27 = 13 * 2 + 1

Lo mismo nos devuelve PHP:

echo 27%13;
1

Nada nuevo bajo el sol, matemáticas básicas. Probemos esto ahora:

>>> -27%13
12

Así es: -27 = 13 * (-3) + 12

Cambiando los signos de D y d:

>>> 27%-13
-12

¡¿Comorll?!?

El resultado esperado es 1:

27 = -13 * (-2) + 1

¿Por qué da -12? ¿Y PHP qué opina de todo esto?

echo 27%-13;
1

Buen chico. ¿Será que un lenguaje tan usado y prestigioso como Python no sabe dividir? ¿Por qué entonces lo escogen en tantas facultades de todo el mundo para la enseñanza? La NASA también lo usa, ¿han escogido un lenguaje que no sabe ni calcular el resto de una división entera?

Siguiendo con PHP:

echo -27%13;
-1

Habíamos visto antes que el resultado era 12 ¿PHP anda también perdido? La definición de la Wikipedia tampoco ayuda a esclarecer que está pasando. En mi opinión, esa definición es inexacta pues dice que la operación módulo calcula el resto de la división euclídea y en la división euclídea se impone la condición r ≥ 0 Cuando no se impone esa condición, y no lo hice en la definición de la operación módulo que di al iniciar esta entrada, las divisiones tendrán dos cocientes y dos residuos posibles: por defecto y por exceso. Mientras que con r ≥ 0 sólo habrá un resultado posible. Si hay un cociente q habrá otro cociente q’ cuyo valor será q + 1 y cada cociente tendrá su respectivo residuo r y r’ Con D=-27 y d=13 tendremos q=-3 y r=12 por un lado y por otro q=-2 y r=-1

-27 = 13 * (-3) + 12

-27 = 13 * (-2) + (-1)

Por lo tanto ambos lenguajes están calculando correctamente. En teoría de números siempre se escoge r ≥ 0 y algunos lenguajes, como Pascal, Scheme o Stata así lo hacen también, para estos lenguajes sí aplica la definición de la Wikipedia, pero la mayoría y los más usados van a escoger la división por exceso o por defecto. Algunos, como PHP, C o C++ escogerán siempre para el resto el signo del dividendo D mientras que otros como Python o Mathematica el del divisor d. Aparentemente para conseguir esta igualdad de signo, usarán la división por exceso o por defecto según sea necesario, aunque lo que realmente hacen es una operación más rápida. Los que usan el mismo signo que el dividendo van realmente rápido, truncan la división:

r = D – d * truncar(D / d)

La función truncar simplemente extermina todos los decimales, o dicho más fino: se redondea al número entero inmediato más cercano a 0. Esto es lo que hace PHP o C:

-1 = -27 – [13*truncar(-27 / 13)] = -27 – [13*truncar(-2.07…)] = -27 – [13*(-2)] = -27 – (-26)

Por otro lado, los que usan el signo del divisor d, usan la función floor (suelo). Esta función proporciona el número entero más pequeño inmediato o igual al número que se le pasa. De manera que por ejemplo Π quedaría en 3 y -Π en -4. Está función se expresa mediante ⌊⌋: floor(x) = ⌊x⌋

r = D – d * ⌊D / d⌋

Esto es lo que Python hace:

12 = -27 – 13[⌊-27 / 13⌋] = -27 – 13[⌊-2.07…⌋] = -27 -13[-3] = -27 + 39

Con la primera extrañeza que nos encontramos, cuando pusimos un divisor negativo, ahora sabemos qué hace Python:

-12 = 27 – (-13)*[⌊27 / -13⌋] = 27 – (-13)⌊-2.07…⌋ = 27 – (-13)*(-3) = 27 – 39

Lenguajes respetuosos con la teoría, como Pascal, hacen esto:

Si d > 0 => q = ⌊D / d⌋

Si d < 0 => q = ⌈D / d⌉

Es decir, si el divisor es negativo usan la función ceiling (techo) Dicha función da el número entero más grande inmediato o igual al número que se le pasa. De manera que Π quedaría en 4 y -Π en -3. Está función se expresa mediante ⌈⌉: ceiling(x) =⌈x⌉

Hay que tener en cuenta que no es esto lo que hacen los lenguajes que cogen el signo del divisor, es decir, no es lo mismo ⌊x⌋ que truncar(), no en el caso de números negativos. Volviendo al ejemplo D = 27 y d = -13 que en Python dio r = -12 mientras que PHP r = 1:

-12 ≠ 27 – (-13*⌈27 / -13⌉) = 27 – (-13*(-2)) = 27 – 26 = 1

Es lo que nos devolvió PHP, porque para números negativos truncar(x) equivale a ⌈x⌉ Para los positivos, en cambio, truncar(x) equivale a ⌊x⌋, por eso para D y d positivos todo lenguaje da el mismo r. Las diferencias surgen con los negativos. Veamos el caso en que ambos son negativos, D = -27 y d = -13. PHP usa truncar(), que en este caso sí equivale a ⌈⌉ :

-27 – (-13* truncar(-27 / -13) = -27 – (-13*truncar(2.07)) = -27 – (-13*2) = -27 + 26 = -1

>>> -27%-13
-1
echo -27%-13;
-1

Mientras que ⌊⌋, que ningún lenguaje la usa, daría:

-27 – (-13*⌊-27 / -13⌋) = -27 – (-13*(⌊2.07⌋) = -27 – (-13)*3 = -27 + 39 = 12

Como q = (D – r) / d Acaba resultando una ecuación sin solución entera:

(-27 – 12) / -13

Por lo tanto r ≠ 12

En la definición de división entera que di al principio introduje una «trampa» para que los resultados de PHP, Python o C fueran correctos: añadí la condición |r|<|d| En teoría de números, la división entera se define sólo para el conjunto de los naturales y la única condición es d ≠ 0 En cambio, para el conjunto de los números enteros (que incluye los naturales más los negativos), se usa la división euclídea, la cual añade la condición r ≥ 0 con el objetivo de obtener unos q y r únicos.

En mi opinión, la razón principal por la que algunos lenguajes usan la división entera también para números negativos es obtener un conjunto de r más amplio. Sin la condición r ≥ 0 se obtienen también r negativos. Con ello, por ejemplo, se consigue reducir el número de colisiones en una tabla de hash. Secundariamente, porque es más rápido el cálculo: truncar es más rápido que redondear. Sacrifican purismo matemático por fines prácticos. Además, el programador puede seguir obteniendo el resto de la división euclídea por otras vías. Puede programar su propia función con ceil() y floor(), o con floor() y truncate() si viene de microsegundos. También es más que probable que el lenguaje tenga una función para obtener dicho resto. Por ejemplo C tiene la función fmod en la librería math.h

Exportar datos a Excel con PHP

Excel

Cuando queremos que el usuario pueda exportar los datos desde una aplicación web para poder abrirlos como una hoja de cálculo lo más recomendable es hacerlo en formato CSV (Comma-Separted Values) Ahora bien, hay casos en que el cliente insiste en que desea que se le abra inmediatamente su Microsoft Excel al hacer click sobre el link o botón. En estos casos, cuando generamos el fichero «al vuelo», la cabecera debe ser:

header('Content-Type: application/vnd.ms-excel');

En vez de:

header('Content-Type: text/csv'; charset=utf-8);

Si los datos contienen caracteres más allá de los primeros 128 ASCII, por ejemplo acentos, al abrirse Excel veremos que estos caracteres no se visualizan correctamente. ¿Por qué? Aunque UTF-8 es de lejos la codificación más usada en la web, y lo más probable es que tu aplicación trabajé con ella, Microsoft Excel sorprendentemente no trabaja con este formato por defecto. Los de Redmond pueden haber perdido parte de su poder pero no su idiosincrasia. ¿Cómo arreglar este desaguisado? Pasando los datos a UTF-16LE (Lower Endian) e indicando la codificación en la cabecera, pues con esta codificación sí trabajan. Para lograrlo, PHP dispone de una función para convertir codificaciones: mb_convert_encoding()

El siguiente código de ejemplo deshace el entuerto. En $participations tenemos los datos a exportar, es un array. En este caso concreto, el código pertenece a una vista y por lo tanto el array ha llegado desde un controlador. El array $header contiene el nombre de cada columna para la hoja de cálculo y $fields contiene los índices de $participations, que coinciden con los nombres de los campos en la base de datos. Sigue leyendo

Cómo instalar XCache en un servidor compartido

La semana pasada quise instalar en un servidor compartido (Hostmonster para más señas) alguno de los diferentes sistemas de caché que existen para PHP. El único que ofrecen es un paquete de PEAR llamado “Cache” pero necesitaba instalar Apc, Xcache, MemCache o Redis. Me puse en contacto con su departamento técnico para consultar si era posible y la respuesta fue un no. Como cuando instalamos Subversion tampoco fueron ni muy optimistas ni proactivos, no hice demasiado caso a su respuesta y me lancé a intentarlo. Como Apc parecía que iba a ser problemático pues por lo que leí necesitaba ser root, lo intenté con Xcache. En primer lugar, en el directorio “home” de mi usuario en Hostmonster creé los directorios y bajé la versión de xCache para la versión de PHP que corre el servidor:

  1. mkdir modules xcache
  2. wget http://xcache.lighttpd.net/pub/Releases/1.3.2/xcache-1.3.2.tar.gz

Después descomprimí el módulo y lo compilé para la versión de PHP del servidor:

  1. tar -zxf xcache-1.3.2.tar.gz
  2. cd xcache-1.3.2
  3. phpize
  4. ./configure –enable-xcache
  5. make

Compruebo que esté bien:

  1. make test

Y ya sólo queda mover el módulo recién compilado a su directorio de destino:

  1. cd modules
  2. mv xcache.so /home2/usuario/modules

Ahora debemos editar php.ini para que PHP empiece a trabajar con Xcache. Añadí las siguientes líneas:

  1. zend_extension = /home2/usuario/modules/xcache.so
  2. zend_extension_ts = /home2/usuario/modules/xcache.so
  3. xcache.shm_scheme = «mmap»
  4. xcache.size = 32M
  5. xcache.count = 8
  6. xcache.slots = 8K
  7. xcache.ttl = 0
  8. xcache.gc_interval = 0
  9. xcache.var_size = 16M
  10. xcache.var_count = 1
  11. xcache.var_slots = 8K
  12. xcache.var_ttl = 0
  13. xcache.var_maxttl = 0
  14. xcache.var_gc_interval = 300
  15. xcache.test = Off
  16. xcache.readonly_protection = Off
  17. xcache.mmap_path = «/dev/zero»
  18. xcache.coredump_directory = «»
  19. xcache.cacher = On
  20. xcache.stat = On
  21. xcache.optimizer = Off
  22. xcache.coverager = Off
  23. xcache.coveragedump_directory = «»

También le podemos añadir un usuario y contraseña, ésta última debe ir “hashed” con md5 según explica la documentación:

  1. xcache.admin.user = «nombre_del_usuario»
  2. xcache.admin.pass = «4c882dcb24bcb1bc225391a602feca7c»

Para que la configuración tenga efecto deberíamos reiniciar los procesos fcgiphp5 pero eso no es siempre posible en un servidor compartido, así que no me quedó otra que esperar a que ello sucediera. Se pueden ver los procesos de la siguiente forma:

  1. ps aux | grep fcgiphp5

A continuación obtenemos la id del proceso y mediante kill mandamos la señal para matarlo. En todo caso, sea de este modo o bien esperando, en el resultado de phpinfo() deberíamos ver esto si XCache está funcionando correctamente:
XCache correctamente instalado

Configuración XCache

Configuración XCache

Instalarlo es muy fácil, ¿verdad? A continuación me puse otra vez en contacto con ellos para preguntarles si tenían algún inconveniente con la instalación pues mejor prevenir a que deshabiliten la web y su respuesta fue que no veían ningún inconveniente. Como pueden observar, en este tipo de servicios de alojamiento web es mejor ser proactivo y lanzarse a ver si es técnicamente posible.

Inefficiencies due to CakePHP ORM implementation

First let me say this article is not a critic against CakePHP (except one point I will talk about later), Object Relational Mapping, far than a trivial thing, it’s a very complicated one.

Let’s begin explaining what this TLA (three-letter acronym) is 🙂 Object Relational Mapping is a programming technique for allowing objects interact with a relational database, trying to allow the programmer to create, insert, update and delete objects in the database without typing a single line of SQL. The technical difficulties are well know (by the name «Object-relational impedance mismatch») and there is a lot of theory about them. In fact, some frameworks like CodeIgniter or Zend Framework avoid not only ORM but the models. This is not because these frameworks don’t follow the MVC pattern but because they follow a different philosophy: as it’s impossible to know how the datasource will be, better to don’t provide models and let them for the developer. They just provide some classes to interact with databases. The fact CakePHP implements ORM helps us to rapid develop an application, CRUD interfaces creation can be automatized, etc. CakePHP is RAD!
Sigue leyendo

Ventajas de los Unix-like para un profesional

Primero permítanme definir quien está a cada lado. Los Unix-like son todos los sistemas operativos Unix, por ejemplo OS X, FreeBSD, OpenBSD, Solaris… En este lado también pongo a Linux, aunque no sea exactamente un UNIX pues la licencia GNU significa «GNU’s not Unix» y una distribución Linux es básicamente el kernel de Linux más las herramientas GNU. Por otro lado… Windows, ¿es que hay alguno más? 🙂

Los Unix-like tienen la ventaja de que nos permiten optimizar esfuerzos pues los conocimientos adquiridos con ellos no caducan. Incluso conocimientos adquiridos en los años 70, antes de que surgieran los ordenadores personales o los modernos lenguajes de programación, siguen siendo válidos hoy en día. El equivalente en historia a 40 años en tecnología serían muchos siglos. En un mundo tan cambiante, donde en menos de una década todo cambia, Unix es la única constante de la que tengo constancia. El lenguaje C, las llamadas al sistema, los comandos, las «pipes»… ahí están desde el principio de los tiempos con pocas variaciones, así como su filosofía, probablemente la responsable de que haya podido sobrevivir tantas décadas.

Los desarrolladores y administradores de sistemas del otro lado siempre tienen que estar pendientes de lo que la compañía propietaria decida. Por ejemplo a finales del año pasado a todos los desarrolladores .NET les preocupó el anuncio de que se enfatizaría HTML y Javascript  como plataforma de desarrollo para Windows 8. ¿Iba .NET a ser extinguido? ¿Y todo el tiempo que le dedicaron y títulos oficiales de Microsoft pagados a precio de oro? Al final parece ser que la Runtime va a ser cambiada a COM y si los programadores .NET no quedan tirados es porque será accesible desde C/C++, .NET, etc. Aunque no sería la primera vez ni la última que una empresa deja abandonados a su suerte a los especialistas en alguna de sus tecnologías. ¿Qué pasaría por ejemplo si Sun abandonase Java? Tres años atrás me habrían tildado de loco por el mero hecho de plantear la posibilidad. Ahora las tecnologías de Sun pertenecen a Oracle, quien adquirió a la primera. ¿Qué futuro reserva Oracle para MySQL y Java? El que más le convenga a sus accionistas, obviamente.

Desde una perspectiva más general, las soluciones tecnológicas de Microsoft, Sun y demás enmascaran el problema solucionado detrás de otros problemas. Un profesional en una de esas soluciones tecnológicas es experto en solucionar esos problemas, pero si desconoce el problema principal, el problema que tecnologías como Java, .NET o Windows Server 200X quieren solucionar, al ser reemplazadas esas soluciones por otras el profesional tiene que partir otra vez, casi de cero, a aprender el reemplazo a la vieja solución y pagar de nuevo certificaciones que cuando proceden de grandes multinacionales son siempre costosas.

Nunca he odiado a Microsoft, algo bastante extendido entre los seguidores de las soluciones open source, bien al contrario le reconozco su gran labor de sacar la informática de las grandes multinacionales, bancos, ejércitos y grandes universidades y llevarla a los hogares, escuelas, oficinas y universidades, algo que les agradezco como esperan: pagando las licencias del software suyo que utilizo, básicamente Windows. Ahora bien, por el futuro de mi carrera profesional, prefiero soluciones open source como muchos de los Unix-like que existen ahora mismo y recomendaría lo mismo.