e elevado a un número imaginario puro

¿Qué significa elevar e a un número complejo? ¡Hasta los autores de Los Simpson lo saben!

Calculan y resuelven eπ*i:

e elevado a pi por i

No por aparecer en Los Simpson es evidente. Siendo b un número natural, sabemos que ab consiste en multiplicar a b veces. También sabemos que cuando b es un entero negativo la definición es otra, es el inverso de ab:

a elevado a menos b

Y que cuando el exponente es un racional, n/b, se trata de la b-enésima raíz de an:

an/b = b√an

Pero ninguna de estas tres definiciones tienen sentido en la exponenciación de e a un número complejo. Para que lo tenga hemos de tener en cuenta las series de Taylor, según las cuales sabemos que:

Taylor e elevado a x

El signo de admiración expresa el factorial. Cuanto más alargamos la serie mayor precisión decimal obtenemos.

En este caso, cuando nos dicen que x es cualquier número, nos lo dicen en un sentido amplio, puede ser también el complejo xi, y por lo tanto:

Taylor e elevado a x por iEsta agrupación final de los pares a la izquierda y los impares a la derecha no es para pasar el rato, pues como por Taylor otra vez sabemos que:

Taylor seno

Y también:

Taylor coseno

Si reemplazamos las infinitas sumas que resultan en el seno y el coseno nos queda la famosa fórmula de Euler:

Formula de EulerPor lo tanto, podemos ver la exponenciación de e a un número complejo z, imaginario puro, ez,como las infinitas sumas que se pueden agrupar entre las que forman el seno y las del coseno. Hay que tener en cuenta que x expresa un ángulo en radianes. Aunque la la circunferencia completa está comprendida entre 0 y 2Π radianes, se puede calcular perfectamente el seno y el coseno de cualquier ángulo x > 2Π pues representa x mod 2Π giros.

Volviendo a la fórmula de Los Simpson, como cos(Π) = -1 y sen(Π) = 0 tenemos:

Calculo de e elevado a pi por iEn un artículo anterior vimos las potencias de la unidad imaginaria y en este hemos visto la exponenciación de e a un número imaginario puro, aquel complejo que sólo tiene parte imaginaria. ¿Qué pasaría si también tuviera parte real, por ejemplo 1 + Πi? Eso lo dejaré para un próximo artículo.

Máscaras de bits

Una máscara de bits son datos para operaciones a nivel de bits. Por ejemplo para el conjunto de los 10 primeros números naturales:

U = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

La máscara que marca los impares es:

M = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]

Mediante la operación NOT sobre la máscara obtenemos los pares:

M = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

Dados dos conjuntos, A y B, y dos máscaras A1 y B1, en las que mediante un 0 se expresa que el elemento no pertenece al conjunto y mediante un 1 que sí pertenece, la operación OR (∨) nos proporciona la unión de ambos A ∪ B mientras que AND (∧) la intersección A ∩ B :

A1 = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]

B1 = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]

A1 ∧ B1 = A ∩ B = [0, 0, 0, 0, 1, 0, 1, 0]

A1 ∨ B1 = A ∪ B = [1, 0, 1, 0, 1, 1, 1, 1, 1, 1]

Las máscaras de bits tienen diferentes usos.

Sirven para definir rangos de IPs y ACL

ACL es el acrónimo de listas de control de acceso. En el protocolo TCP/IP las direcciones IP vienen acompañas de su máscara. Si ejecuto ifconfig en mi ordenador aparece la siguiente información:

ifconfig

IP y máscara

Sigue leyendo

Zen, matemáticas y la paradoja de Sorites

Montón de arena o duna o n granos de arena

¿Montón de arena? ¿Duna? ¿N granos de arena?

Hace años leí algunos capítulos de un fragmento de un libro Zen escrito en algún momento entre los siglos XVI y XIX, ya no recuerdo, de la escuela Soto o Rinzai, tampoco lo recuerdo, de un autor que, como probablemente habrás adelantado, tampoco recuerdo, pero sí, era japonés. En definitiva, muy Zen todo. Lo que sí recuerdo bien es un símil realizado con la evolución de un fuego recién empezado con unos leños hasta su consumición completa. ¿En qué momento podemos decir que dejaron de haber leños para haber sólo ceniza? Creo que con este ejemplo el autor quería hacer notar las limitaciones que nuestros conceptos mentales tienen para ayudarnos a entender la realidad.

Bastantes años después he caído, navegando por Internet, en la paradoja de Sorites. Esta paradoja entiendo que quiere hacernos caer en la cuenta de algo muy parecido, poniendo como ejemplo no la combustión de un pequeño fuego sino un montón de arena. Sorites es como se pronuncia en griego σωρείτης palabra que significa montón o cúmulo. La paradoja parte del hecho de que estaremos todos de acuerdo en que:

  1. Dos o tres granos de arena no son un montón.
  2. 100.000 o 1.000.000 sí lo son.
  3. Si dos o tres granos de arena – llamemos n a esos dos o tres – no son un montón, tampoco lo serán n+1
  4. Un montón de n granos no dejará de serlo por quitarle uno (n-1)

Mediante inducción matemática se comprueba que la primera y tercera característica niegan la segunda, es decir, que 100.000 granos (ni un millón) forman un montón.

Llamemos a ser un montón tener la propiedad P. La primera característica nos dice que para n = 1 no existe la propiedad P, y que tampoco existe para n = 2 ni para n = 3. La tercera nos dice que dado que Pn no es un montón tampoco lo será Pn+1 = n+1 Tenemos:

  1. ¬P(1)
  2. ¬P(2)
  3. ¬P(n) ⇒ ¬P(n+1)

Supongamos que hay un número mínimo de granos de arena a partir del cual sí se verifica P, llamaremos m a ese número. Tenemos entonces que m-1 no es un montón y a partir de m granos sí lo es. También sabemos por la característica 1 que m > 1 y por la 3 sabemos que m -1 debe cumplir:

P(m-1) ⇒ P(m -1 + 1)

Es decir, que P(m-1) = P(m) y esto es una contradicción pues hemos impuesto que m es el elemento mínimo a partir del cual tenemos la propiedad P (es un montón) y por debajo de m granos no tenemos esa propiedad.

Por el mismo método de la inducción matemática se demuestra a partir de las características segunda y cuarta de un montón que la primera es falsa, es decir, que tan solo dos o tres granos de arena sí son un montón. Incluso que ningún grano también lo es.

Por lo tanto, no sólo conceptos como la belleza o la armonía son difíciles de definir, sino que identificar conceptos que representan objetos físicos como la madera o la ceniza, incluso los medibles como la gordura o la delgadez (peso), o un montón (número de elementos que lo forman) nos pueden resultar evidentes cuando realmente no lo son.

Las potencias de la unidad imaginaria como clase de equivalencia

El número imaginario i es aquel que permite resolver, entre otras cosas, la ecuación:

i2 = -1

Por lo tanto i = √-1

Podemos ver que sus potencias enteras son:

i0 = 1

i1 = i (= √-1)

i2 = -1

i3 = i * i2 = i * (-1) = -i

i4 = i2 * i2 = -1 * (-1) = 1

i5 = i2 * i3 = -1 * (-i) = i

in = …

Si seguimos la serie vemos que emerge un patrón: 1, i, -1, -i, …

Así como vimos que las congruencias se podían tratar como clases de equivalencia, vemos aquí que las potencias de i se pueden tratar como la clase de equivalencia Z4

Sabemos que Z4 = {[0], [1], [2], [3]} es decir, el total de restos posibles de 4 y sabemos una n potencia de i que pertenece a cada clase:

0 = i0

1 = i1

2 = i2

3 = i3

Con todo esta información no habrá potencia que se nos resista. Si queremos calcular i54 sólo tendremos que calcular el resto de la división de 54 entre 4, que es 2 y por lo tanto pertenece a la misma clase que i2 , por lo que podemos afirmar que i54 = i2 = -1 También podemos afirmar que i54 es congruente con i2 La fórmula general es:

in = i4 mod (n)

Esto también puede enfocarse desde una perspectiva más gráfica. Multiplicar por i es rotar en el plano 90º hacía atrás y multiplicar por -i es avanzar 90º Por más que rotemos siempre acabaremos en uno de los 4 puntos:

El número imaginario en el plano cartesiano complejo

El número imaginario i en el plano cartesiano complejo

Clase que permite transacciones anidadas con PDO

PDO, acrónimo de PHP Data Objects es un interfaz para acceder a bases de datos desde PHP. A diferencia de las extensiones mysql y mysqli, que son exclusivas para MySQL, PDO puede trabajar con diferentes sistemas gestores de bases de datos, siempre y cuando haya driver para el mismo.

Las transacciones sirven para garantizar la integridad referencial de los datos. Una transacción está formada por varias órdenes SQL y bien se ejecutan todas las consultas en bloque o si alguna falla se vuelve al estado inicial antes de empezar la transacción, sin ejecutarse ninguna de ellas. Las transacciones deben cumplir con las propiedades ACID: Atomicidad, Consistencia, Isolation (aislamiento) y Durabilidad. (Nada que ver con el subgénero de música electrónica de finales de los 80 🙂 )

Las transacciones se anidan cuando existiendo una transacción en curso, se inicia otra. Esto por ejemplo sucede cuando desde un método donde se ha iniciado una transacción, para reciclar código (una de las virtudes de la programación orientada a objetos) se llama a otro método que inicia otra transacción.

Transacciones anidadas

Todo fue bien hasta el final y se ejecutan en bloque todas las transacciones (COMMIT)

Transacciones anidadas

¡Ups, algo fallo cuando ya casi finalizaba! ¡Déjalo todo como estaba! (ROLLBACK)

Desgraciadamente, desarrollando en LAMP, nada más iniciarse la segunda transacción se producirá un error fatal. MySQL no soporta las transacciones anidadas. En su documentación afirma que después de ejecutarse un BEGIN TRANSACTION ciertas órdenes producirán un COMMIT, entre ellas BEGIN TRANSACTION. Tampoco las soporta PostgreSQL. Una solución parcial que ambos sistemas incorporan son los SAVE POINTS.

A continuación viene el esquema de una clase que mediante los SAVE POINTS y controlando el número de transacciones anidadas mediante la propiedad transactionDepth, consigue algo parecido a anidar transacciones y por lo tanto evita el error fatal antes mencionado.

Si tu clase extiende la clase PDO, el método execute puede ser reemplazado llamando simplemente a $this->exec() Como digo, esta clase es un esquema para entender la idea, no está pensada para funcionar directamente sino que el programador interesado en ella deberá adaptarla.

class Db { 
  static private $instance = null; 
  static private $connection = null;
  protected $transactionDepth = 0; 
 
  private function __construct() { 
  }
  
  private function _connect() { 
     if (self::$connection === null) {
         try {
            /* Código para conectarse a la BD */
             self::$connection = new PDO('mysql:host=localhost', 'root', 'root');
         } catch (PDOException $e) {
            echo "error pdo: " . $e->getMessage();
         }
      }

      return self::$connection;
   }
   
   /* Nada que clonar en el patrón de diseño Singleton */
   private function __clone()
   {
     
   }

   static public function getInstance()
   {
      if (is_null(self::$instance)) {
         self::$instance = new self();
      }

      return self::$instance;
   }

   static public function closeConnection()
   {
      self::$instance = null;

      if (isset(self::$connection)) {
         self::$connection = null;
      }
   }

   public function getConnection()
   {
      return $this->_connect();
   }

   protected function prepare($query, $params = array())
   {
      $stmt = $this->getConnection()->prepare($query);
      if (is_array($params)) {
         foreach ($params as $param => $value) {
            if (is_bool($value)) {
               $type = PDO::PARAM_BOOL;
            } elseif ($value === null) {
               $type = PDO::PARAM_NULL;
            } elseif (is_integer($value)) {
               $type = PDO::PARAM_INT;
            } else {
               $type = PDO::PARAM_STR;
            }
            $stmt->bindValue(":$param", $value, $type);
         }
      }

      return $stmt;
   }

   public function execute($sql, $params = array())
   {
      $stmt = $this->prepare($sql, $params);
      $stmt->execute();
      $stmt->closeCursor();

      return $stmt->rowCount();
   }

   public function begin()
   {
      if ($this->transactionDepth === 0) {
         $this->getConnection()->beginTransaction();
      }else{
         $this->execute("SAVEPOINT LEVEL{$this->transactionDepth}");
      }
      $this->transactionDepth++;
   }

   public function commit()
   {
      $this->transactionDepth--;
      if ($this->transactionDepth === 0) {
         return $this->getConnection()->commit();
      }else{
         return $this->execute("RELEASE SAVEPOINT LEVEL{$this->transactionDepth}");
      }
   }

   public function rollback()
   {
      if ($this->transactionDepth === 0) {
         throw new LogicException("Ninguna transacción en curso para retroceder");
      }
      $this->transactionDepth--;
      if ($this->transactionDepth === 0) {
         return $this->getConnection()->rollback();
      }else{
         return $this->execute("ROLLBACK TO SAVEPOINT LEVEL{$this->transactionDepth}");
      }
   }
}

El código también está disponible en Github.