28. Operaciones con vectores

Sumar, restar y escalar vectores permite combinar desplazamientos, calcular direcciones y construir nuevos datos. Las operaciones se realizan componente a componente y conservan la dimensión.

28.1 Introducción

Los vectores representan cantidades con varias componentes relacionadas. Para manipularlos necesitamos operaciones que respeten su estructura y produzcan resultados con una interpretación clara.

Las operaciones fundamentales son la suma, la resta y la multiplicación por un escalar. A partir de ellas se construyen combinaciones lineales y numerosas técnicas utilizadas en programación.

Las operaciones vectoriales se aplican a cada componente, manteniendo siempre su posición.

28.2 Compatibilidad de dimensiones

Para sumar, restar o comparar dos vectores, ambos deben pertenecer al mismo espacio ℝn. No tiene sentido sumar directamente un vector de dos componentes con uno de tres.

(u1, ..., un) y (v1, ..., vn) deben tener la misma dimensión.
function mismaDimension(u, v) {
  return Array.isArray(u) && Array.isArray(v) && u.length === v.length;
}

console.log(mismaDimension([1, 2], [3, 4]));    // true
console.log(mismaDimension([1, 2], [3, 4, 5])); // false

28.3 Igualdad de vectores

Dos vectores son iguales si tienen la misma dimensión y todas sus componentes correspondientes son iguales.

u = v ⇔ ui = vi para todo i

Con resultados decimales conviene comparar mediante una tolerancia.

function vectoresIguales(u, v, tolerancia = 1e-10) {
  return u.length === v.length &&
    u.every((valor, i) => Math.abs(valor - v[i]) <= tolerancia);
}

console.log(vectoresIguales([0.1 + 0.2, 1], [0.3, 1])); // true

28.4 Suma de vectores

La suma se calcula agregando las componentes correspondientes:

u + v = (u1 + v1, ..., un + vn)

Por ejemplo, (2, −1, 4) + (3, 5, −2) = (5, 4, 2).

function sumarVectores(u, v) {
  if (u.length !== v.length) throw new Error("Dimensiones incompatibles");
  return u.map((valor, i) => valor + v[i]);
}

console.log(sumarVectores([2, -1, 4], [3, 5, -2])); // [5, 4, 2]

28.5 Interpretación geométrica de la suma

Para sumar u + v se puede colocar el origen de v en el extremo de u. El vector resultante une el origen de u con el extremo trasladado de v.

También puede construirse el paralelogramo cuyos lados son u y v; la diagonal que parte del origen representa u + v.

const origen = [1, 2];
const u = [3, 1];
const v = [-1, 4];
const extremo = origen.map((coordenada, i) => coordenada + u[i] + v[i]);

console.log(extremo); // [3, 7]

Esta interpretación muestra que la suma combina desplazamientos sucesivos.

28.6 Propiedades de la suma

PropiedadExpresión
Conmutativau + v = v + u
Asociativa(u + v) + w = u + (v + w)
Elemento neutrou + 0 = u
Elemento opuestou + (−u) = 0

Estas propiedades permiten reorganizar cálculos sin cambiar el resultado matemático.

28.7 Vector opuesto

El opuesto de u cambia el signo de cada componente. Tiene la misma magnitud y dirección, pero sentido contrario.

Si u = (u1, ..., un), entonces −u = (−u1, ..., −un).
const opuesto = vector => vector.map(valor => -valor);
const u = [4, -3, 2];

console.log(opuesto(u)); // [-4, 3, -2]

28.8 Resta de vectores

Restar v equivale a sumar su opuesto:

u − v = u + (−v) = (u1 − v1, ..., un − vn)
function restarVectores(u, v) {
  if (u.length !== v.length) throw new Error("Dimensiones incompatibles");
  return u.map((valor, i) => valor - v[i]);
}

console.log(restarVectores([7, 4, 1], [2, -1, 3])); // [5, 5, -2]

28.9 Resta para obtener una dirección

Dados un origen A y un destino B, el vector que apunta desde A hasta B se calcula como B − A.

function direccionHacia(origen, destino) {
  return destino.map((coordenada, i) => coordenada - origen[i]);
}

const personaje = [2, 3];
const objetivo = [8, 1];
console.log(direccionHacia(personaje, objetivo)); // [6, -2]

El vector resultante todavía no tiene longitud unitaria; su normalización se estudiará en temas posteriores.

28.10 Multiplicación por un escalar

Multiplicar un vector v por un número k multiplica cada componente:

kv = (kv1, ..., kvn)
  • Si |k| > 1, el vector se alarga.
  • Si 0 < |k| < 1, se acorta.
  • Si k < 0, también cambia de sentido.
  • Si k = 0, se obtiene el vector cero.
function multiplicarPorEscalar(k, vector) {
  return vector.map(valor => k * valor);
}

console.log(multiplicarPorEscalar(2, [3, -1]));    // [6, -2]
console.log(multiplicarPorEscalar(-0.5, [4, 2])); // [-2, -1]

28.11 Propiedades del producto por escalares

PropiedadExpresión
Distributiva respecto de vectoresk(u + v) = ku + kv
Distributiva respecto de escalares(k + m)v = kv + mv
Asociativak(mv) = (km)v
Identidad1v = v
Producto por cero0v = 0
const sumar = (u, v) => u.map((x, i) => x + v[i]);
const escalar = (k, v) => v.map(x => k * x);
const u = [1, 2];
const v = [3, -1];

console.log(escalar(2, sumar(u, v)));
console.log(sumar(escalar(2, u), escalar(2, v)));
// Ambos resultados son [8, 2].

28.12 Combinaciones lineales

Una combinación lineal suma vectores multiplicados por escalares:

k1v1 + k2v2 + ... + krvr
function combinacionLineal(vectores, escalares) {
  if (!vectores.length || vectores.length !== escalares.length) {
    throw new Error("Datos incompatibles");
  }
  return vectores[0].map((_, componente) =>
    vectores.reduce(
      (suma, vector, i) => suma + escalares[i] * vector[componente],
      0
    )
  );
}

console.log(combinacionLineal([[1, 2], [3, -1]], [2, -4])); // [-10, 8]

28.13 Sumar varios vectores

Una trayectoria puede contener muchos desplazamientos. El desplazamiento neto se obtiene sumándolos todos.

function sumarTodos(vectores) {
  if (vectores.length === 0) return [];
  return vectores.reduce(
    (acumulado, vector) => acumulado.map((valor, i) => valor + vector[i]),
    Array(vectores[0].length).fill(0)
  );
}

const movimientos = [[3, 0], [0, 4], [-1, -2]];
console.log(sumarTodos(movimientos)); // [2, 2]

El resultado es independiente del orden matemático de la suma, aunque con muchos decimales el redondeo computacional puede causar diferencias diminutas.

28.14 Implementación inmutable

Las funciones anteriores crean arreglos nuevos y no modifican sus argumentos. Este estilo reduce efectos secundarios y facilita reutilizar los vectores originales.

const u = [1, 2];
const v = [3, 4];
const resultado = u.map((valor, i) => valor + v[i]);

resultado[0] = 99;
console.log(u); // [1, 2]
console.log(v); // [3, 4]

28.15 Interpolación lineal

La interpolación lineal encuentra puntos entre A y B mediante:

lerp(A, B, t) = A + t(B − A)

Para t = 0 se obtiene A; para t = 1, B; y para t = 0.5, el punto medio.

function interpolar(A, B, t) {
  return A.map((valor, i) => valor + t * (B[i] - valor));
}

console.log(interpolar([0, 10], [20, 30], 0.25)); // [5, 15]
console.log(interpolar([0, 10], [20, 30], 0.5));  // [10, 20]

28.16 Movimiento con velocidad y tiempo

Si la velocidad v es constante durante un intervalo Δt, el desplazamiento es Δtv y la nueva posición es:

posiciónNueva = posición + velocidad · Δt
function actualizarPosicion(posicion, velocidad, deltaTiempo) {
  return posicion.map(
    (coordenada, i) => coordenada + velocidad[i] * deltaTiempo
  );
}

console.log(actualizarPosicion([10, 5], [4, -2], 0.5)); // [12, 4]

28.17 Producto componente a componente

Algunas aplicaciones multiplican componentes correspondientes. Esta operación se llama producto de Hadamard:

u ⊙ v = (u1v1, ..., unvn)
function productoHadamard(u, v) {
  if (u.length !== v.length) throw new Error("Dimensiones incompatibles");
  return u.map((valor, i) => valor * v[i]);
}

console.log(productoHadamard([2, 3, 4], [5, -1, 0.5])); // [10, -3, 2]

No debe confundirse con el producto escalar ni con el producto vectorial, que se estudiarán más adelante. Tampoco existe una división vectorial estándar única.

28.18 Validación y errores frecuentes

Una función robusta debe comprobar que los datos sean arreglos de igual dimensión con componentes numéricas finitas.

function validarPares(u, v) {
  const validos = Array.isArray(u) && Array.isArray(v) &&
    u.length === v.length && u.length > 0 &&
    [...u, ...v].every(Number.isFinite);
  if (!validos) throw new Error("Vectores inválidos o incompatibles");
}

try {
  validarPares([1, 2], [3, NaN]);
} catch (error) {
  console.log(error.message);
}

Otros errores comunes son invertir el orden de una resta, confundir producto por escalar con producto de vectores, modificar datos compartidos y comparar decimales mediante igualdad exacta.

28.19 Qué debes recordar de este tema

  • Los vectores que se suman, restan o comparan deben tener igual dimensión.
  • La suma y la resta se realizan componente a componente.
  • Restar v equivale a sumar su opuesto.
  • El vector desde A hasta B es B − A.
  • El producto por un escalar multiplica todas las componentes.
  • Las combinaciones lineales reúnen sumas y productos por escalares.
  • La interpolación se expresa como A + t(B − A).
  • El producto de Hadamard no es el producto escalar ni el vectorial.

28.20 Conclusión

Las operaciones fundamentales permiten combinar, invertir y escalar direcciones en cualquier dimensión. Su implementación componente a componente se adapta naturalmente a arreglos y constituye la base de cálculos geométricos más avanzados.

En el próximo tema estudiaremos la norma o módulo de un vector, que permite medir su longitud.