Optimizaciones inútiles del código en PHP

En las aplicaciones donde la velocidad no es determinante – categoría a la que pertenecen muchas aplicaciones web – el código, antes que optimizado, debe estar estructurado. Como los requerimientos están cambiando frecuentemente, el tiempo del programador es mucho más importante (y costoso) que el tiempo de CPU. Además, lo que puede parecernos una optimización, a veces no lo es. Veamos un ejemplo con los desplazadores de bits.

La teoría nos dice que tanto la operación de multiplicación como la de división requieren cierto tiempo de computación, especialmente esta última. Ahora bien, si esta operación se hace con una potencia de 2, se convierte en algo trivial para la CPU gracias a los desplazadores, unos sencillos bloques combinacionales formados por unas pocas puertas lógicas.

Los desplazadores tienen una señal de entrada y una de salida de n bits ambas. La señas de salida se obtiene desplazando los bits de entrada m veces hacia la derecha o hacia la izquierda El desplazamiento a la izquierda equivale a multiplicar por 2m mientras que a la derecha realiza la división entera por 2m. En el caso del desplazamiento a la derecha o división, en función del valor que se asigne a los «nuevos» bits, existen dos tipos de desplazadores:

  • Lógicos: Se ponen a 0.
  • Aritméticos: Se ponen al mismo valor que el bit de más peso de la entrada. Sirven para que los números codificados en complemento a dos conserven el signo.
Desplazador aritmético y lógico de 4 bits

Dos desplazadores de 4 bits: El de arriba lógico y el de abajo aritmético. Ambos desplazan 01 (2(10) bits a la derecha, i.e., dividen por 2.

Sigue leyendo

Expresión analítica y geométrica del producto escalar

El producto escalar es una operación entre dos vectores que retorna un escalar, es decir, un número real. Existen dos definiciones de esta operación que darán el mismo resultado, aunque inicialmente no sea muy intuitivo que así sea: la analítica y la geométrica. Veamos la primera de ellas:

Dados dos vectores del espacio vectorial ℝn, u = (u1, u2, …, un) y v = (v1, v2, …, vn), se define el producto escalar de ambos, u · v como:

u·v = u1 · v1 + u2 · v2 + … + un · vn

En todo espacio vectorial euclídeo, y por lo tanto normado, podemos usar también la definición geométrica, esta nos dice que el producto escalar de dos vectores es el producto del módulo (o norma) de cada uno de ellos por el coseno del ángulo que forman:

Producto escalar

(2)

A continuación, veamos dos ejemplos sencillos en el plano cartesiano, ℝ2, para ver que ambas formas arrojan el mismo resultado. Ya nos advirtió Johan Cruyff: «Un palomo no hace verano», por lo que estos dos ejemplos no pretenden demostrar nada sino ejemplificar este concepto poco intuitivo. El primer ejemplo consistirá en los vectores u = (2, 2) y v = (2, -2):

ejemplo 1 Sigue leyendo

Cómo simplificar una relación Many-To-Many consigo misma

En esta breve entrada expongo cómo el programador puede facilitarse un poco su actividad cuando en Doctrine establezca una relación de una entidad consigo misma. El código que se expone es de una entidad del framework Symfony, pero fácilmente se puede adaptar a cualquier entorno PHP donde, eso sí, se esté empleando este conocido ORM.

Según la documentación de Doctrine, el código para la relación Many-To-Many (de muchos a muchos) de una entidad que se referencia a si misma, por ejemplo un producto que puede tener otros productos relacionados, sería:

class Product
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ManyToMany(targetEntity="Product", mappedBy="myProducts")
     */
    private $relatedWithMe;

    /**
     * @ManyToMany(targetEntity="Product", inversedBy="relatedWithMe", fetch="EAGER")
     * @JoinTable(name="related_products",
     *      joinColumns={@JoinColumn(name="product_id", referencedColumnName="id")},
     *      inverseJoinColumns={@JoinColumn(name="related_product_id", referencedColumnName="id")}
     *      )
     */
    private $myProducts;

    public function __construct()
    {
        $this->relatedWithMe = new ArrayCollection();
        $this->myProducts = new ArrayCollection();
    }

    public function addRelatedWithMe(Product $relatedWithMe): self
    {
        if (!$this->relatedWithMe->contains($relatedWithMe)) {
            $this->relatedWithMe[] = $relatedWithMe;
            $relatedWithMe->addMyProduct($this);
        }

        return $this;
    }

    public function removeRelatedWithMe(Product $relatedWithMe): self
    {
        if ($this->relatedWithMe->contains($relatedWithMe)) {
            $this->relatedWithMe->removeElement($relatedWithMe);
            $relatedWithMe->removeMyProduct($this);
        }

        return $this;
    }

    /**
     * @return Collection|Product[]
     */
    public function getMyProducts(): ?Collection
    {
        return $this->myProducts;
    }

    public function addMyProduct(Product $myProduct): self
    {
        if (!$this->myProducts->contains($myProduct)) {
            $this->myProducts[] = $myProduct;
        }

        return $this;
    }

    public function removeMyProduct(Product $myProduct): self
    {
        if ($this->myProducts->contains($myProduct)) {
            $this->myProducts->removeElement($myProduct);
        }

        return $this;
    }

Sigue leyendo

i elevado a i

Una serie de artículos acerca de la exponenciación con números complejos, que di por finalizada en su tercera entrega, y a los que el lector puede recurrir si no entiende algo de lo que en el presente artículo se explica, voy a ampliarla para el curioso caso de ii, y digo curioso pues el resultado es un número real.

Vimos que la generalización de la exponenciación, ab, sean a y b reales1 o complejos, es:

Exponenciación generalizada

En el presente caso, a = i, y si bien el logaritmo complejo existe, aplicando la fórmula de Euler, podremos obtener la forma exponencial para calcular fácilmente ii. En primer lugar, vamos a expresar i en forma polar para obtener dos datos que necesitaremos: el módulo y el argumento. El módulo, obviamente, será 1 y el argumento será π/2 radianes, pues i forma un ángulo recto con la parte real o eje de las ordenadas:

El número imaginario en el plano cartesiano complejo

Sigue leyendo

Ecuación de la asíntota oblicua

Es frecuente que a los alumnos se les enseñe que, si una función tiene un asíntota oblicua que viene dada por y = ax + b, los términos a y b se calcularán a partir de dos fórmulas que deben memorizar:

término b

(1)

término a

(2)

Pero, ¿de dónde provienen? Si tenemos poca memoria y/o preferimos entender el porqué de las cosas, algo bastante conveniente en matemáticas, debemos tener en cuenta que, para una x infinitamente grande, por las propiedades de los límites, se cumplirá f(x) – y = 0:

ecuación asintota oblicua

(3)

Sigue leyendo