# ============================================
# PI por: Leibniz, Wallis y Euler (MicroPython)
# Tabla: pi_est y error por método
# ============================================
try:
import math
PI_REF = math.pi
except ImportError:
PI_REF = 3.141592653589793
# ----------------------------
# Kahan summation (opcional)
# ----------------------------
class KahanSum:
def __init__(self):
self.s = 0.0
self.c = 0.0
def add(self, x):
y = x - self.c
t = self.s + y
self.c = (t - self.s) - y
self.s = t
def value(self):
return self.s
# ----------------------------
# Leibniz: pi = 4 * sum_{n=0..N-1} (-1)^n/(2n+1)
# ----------------------------
def pi_leibniz(N, use_kahan=True):
if N <= 0:
return 0.0
sign = 1.0
denom = 1.0
if use_kahan:
acc = KahanSum()
for _ in range(N):
acc.add(sign / denom)
sign = -sign
denom += 2.0
return 4.0 * acc.value()
else:
s = 0.0
for _ in range(N):
s += sign / denom
sign = -sign
denom += 2.0
return 4.0 * s
# ----------------------------
# Wallis: pi = 2 * Π_{n=1..N} (2n/(2n-1))*(2n/(2n+1))
# ----------------------------
def pi_wallis(N):
if N <= 0:
return 0.0
p = 1.0
for n in range(1, N + 1):
two_n = 2.0 * n
p *= (two_n / (two_n - 1.0)) * (two_n / (two_n + 1.0))
return 2.0 * p
# ----------------------------
# Euler: pi/2 = Σ a_n, a0=1, a_{n+1}=a_n*(n+1)/(2n+3)
# ----------------------------
def pi_euler(N, use_kahan=True):
if N <= 0:
return 0.0
term = 1.0 # a0
if use_kahan:
acc = KahanSum()
acc.add(term)
for n in range(0, N - 1):
term *= (n + 1.0) / (2.0 * n + 3.0)
acc.add(term)
return 2.0 * acc.value()
else:
s = term
for n in range(0, N - 1):
term *= (n + 1.0) / (2.0 * n + 3.0)
s += term
return 2.0 * s
# ----------------------------
# Tabla comparativa: pi y error absoluto
# ----------------------------
def tabla_pi_y_error(N_list):
print("PI_REF =", PI_REF)
header = (
"N "
"pi_Leibniz err_L "
"pi_Wallis err_W "
"pi_Euler err_E"
)
print(header)
print("-" * len(header))
for N in N_list:
pL = pi_leibniz(N, use_kahan=True)
pW = pi_wallis(N)
pE = pi_euler(N, use_kahan=True)
eL = abs(PI_REF - pL)
eW = abs(PI_REF - pW)
eE = abs(PI_REF - pE)
# Formato compacto y legible en consola MicroPython
print(
"{:<6d} {:<13.10f} {:<10.3e} {:<13.10f} {:<10.3e} {:<13.10f} {:<10.3e}".format(
N, pL, eL, pW, eW, pE, eE
)
)
# ----------------------------
# Demo
# ----------------------------
if __name__ == "__main__":
# Ajusta según tu micro: Leibniz converge MUY lento (error ~O(1/N))
N_list = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000]
tabla_pi_y_error(N_list)