WhatsApp

  

Algoritmo Pi de Liu Hui: teoría, implementación en Python y comparativas modernas

Descubre el algoritmo de Liu Hui para calcular π, su fundamento matemático, ejemplos completos en Python y cómo se compara con otros métodos actuales como Machin, Monte Carlo y BBP.

Algoritmo Pi de Liu Hui

Una mirada profunda al método milenario de Liu Hui para aproximar π, con ejemplos prácticos en Python y una comparativa con los algoritmos más usados hoy.

1. Contexto histórico y matemático

El matemático chino Liu Hui (c. 225‑295 d.C.) describió en su comentario al "Jiuzhang Suanshu" (Nueve capítulos sobre el arte de calcular) un método geométrico basado en la aproximación por polígonos inscritos. Su idea: cuanto mayor sea el número de lados del polígono regular inscrito en un círculo, más cerca estará su perímetro del valor real de la circunferencia.

La fórmula esencial es:

π ≈ n × sin(180°/n)
donde n es el número de lados del polígono. Liu Hui utilizó una técnica de doble del número de lados en cada iteración, reduciendo el error exponencialmente.

2. Derivación paso a paso

  1. Comenzar con un hexágono inscrito (n = 6).
  2. Calcular la longitud del lado usando trigonometría: a₀ = sin(π/6).
  3. En cada iteración k duplicar n y actualizar la longitud del lado con la relación:
     a_{k+1} = \sqrt{2 - \sqrt{4 - a_k^2}} 
    (derivada de la fórmula del ángulo medio).
  4. Obtener la aproximación de π como π_k = n_k × a_k / 2.

Esta recursión evita el cálculo directo de sin en cada paso, lo que era crucial en la era pre‑calculadora.

3. Implementación en Python

3.1 Versión básica (legibilidad)

import math
def liu_hui_pi(iterations: int = 5) -> float:
    """Calcula π usando el algoritmo de Liu Hui.
    Args:
        iterations: Número de veces que se duplica el número de lados (n = 6·2ⁱ).
    Returns:
        Aproximación de π.
    """
    n = 6                       # número inicial de lados
    a = math.sin(math.pi / n)   # longitud del lado del hexágono
    for _ in range(iterations):
        # fórmula del ángulo medio sin usar sin directamente
        a = math.sqrt(2 - math.sqrt(4 - a * a))
        n *= 2
    return n * a / 2
print(f"π ≈ {liu_hui_pi(10):.15f}")

3.2 Versión optimizada (uso de decimal para alta precisión)

from decimal import Decimal, getcontext
def liu_hui_pi_decimal(iterations: int = 15, prec: int = 50) -> Decimal:
    getcontext().prec = prec
    n = Decimal(6)
    a = (Decimal(1).sqrt() / Decimal(2)).quantize(Decimal(1) / (10 ** prec))  # sin(π/6) = 0.5
    for _ in range(iterations):
        a = (Decimal(2) - (Decimal(4) - a * a).sqrt()).sqrt()
        n *= 2
    return (n * a) / 2
print('π ≈', liu_hui_pi_decimal(20, 80))

Con Decimal se pueden alcanzar más de 70 cifras correctas con apenas 20 iteraciones.

4. Comparativa con otros algoritmos populares

Liu Hui vs Machin (arctan)

  • Convergencia: Machin converge ~ quadráticamente; Liu Hui es lineal pero con factor 2 en cada iteración.
  • Coste computacional: Liu Hui solo necesita una raíz cuadrada por iteración; Machin requiere varias evaluaciones de atan y multiplicaciones de alta precisión.
  • Facilidad de implementación: Liu Hui es más sencillo en entornos sin librerías trigonométricas.

Liu Hui vs Monte Carlo

  • Precisión: Monte Carlo necesita millones de puntos para alcanzar la precisión de Liu Hui con 10 iteraciones.
  • Determinismo: Liu Hui produce siempre la misma aproximación; Monte Carlo es probabilístico.
  • Uso de recursos: Monte Carlo consume más CPU y memoria por punto generado.

En entornos con recursos limitados (microcontroladores, sistemas embebidos) Liu Hui sigue siendo competitivo por su bajo consumo de operaciones.

5. Buenas prácticas y optimizaciones

  • Precisión de punto flotante: Para float64 el número máximo de iteraciones útiles es ~ 30, ya que la raíz cuadrada pierde 1‑2 bits de precisión cada paso.
  • Vectorización: En Python con numpy se pueden calcular múltiples iteraciones simultáneamente, reduciendo la sobrecarga de bucle.
  • Paralelismo: Cada iteración depende del anterior, pero el cálculo de la raíz puede delegarse a la librería math que ya está optimizada para SIMD.
  • Control de errores: Comparar la salida con math.pi y detener cuando abs(π_k - math.pi) < 10^{-p} donde p es la precisión requerida.

6. Solución de problemas comunes

SíntomaCausa probableSolución
Resultado nan después de pocas iteracionesDesbordamiento de raíz cuadrada por falta de precisión (Decimal con precisión insuficiente)Aumentar prec en getcontext().prec o usar float con math.sqrt para rangos pequeños.
La aproximación no mejora tras más iteracionesLímite de precisión del tipo de dato (float64)Cambiar a Decimal o mpmath con mayor precisión.
Rendimiento lento en DecimalUso excesivo de precisión innecesariaCalcular el número mínimo de iteraciones que cumpla la precisión deseada y limitar prec a ese valor.

7. Escalabilidad y casos de uso reales

El algoritmo se utiliza en:

  • Educación: Demostraciones de convergencia geométrica en cursos de cálculo.
  • Sistemas embebidos: Cálculo rápido de π en microcontroladores sin FPU.
  • Benchmarking: Comparación de rendimiento de librerías de aritmética de precisión arbitraria.

© 2025 BlogTech – Todos los derechos reservados.



Algoritmo Pi de Liu Hui: teoría, implementación en Python y comparativas modernas
ASIMOV Ingeniería S. de R.L. de C.V., Emiliano Nava 15 noviembre, 2025
Compartir
Iniciar sesión dejar un comentario

  
Algoritmo de Partición Entera: Conceptos, Implementación en Python y Mejores Prácticas
Aprende todo sobre el algoritmo de Partición Entera, su teoría, implementaciones en Python (recursiva, memoizada y dinámica), comparativas de rendimiento y casos de uso reales.