#!/usr/bin/env python # coding: utf-8 # In[10]: import math # # Aproximación para $\ln(x)$ # El logaritmo natural de $(1 + x)$ puede aproximarse mediante la serie de Maclaurin (serie de Taylor para $\ln(1 + x)$ centrada en 0): # # $$ # \ln(1 + x) = \sum_{n=1}^{\infty} \frac{(-1)^{n+1} \cdot x^n}{n} = x - \frac{x^2}{2} + \frac{x^3}{3} - \frac{x^4}{4} + \cdots \quad \text{(válido para } -1 < x \leq 1\text{)} # $$ # # - Implementar en Python una función que calcule esta aproximación para un valor $x$ (en el rango $(-1, 1]$) y un número de términos $N$. # - Comparar el resultado con el valor real de $\ln(1 + x)$ (usando $\texttt{math.log(1 + x)}$). # # In[11]: def approx_ln(x,N): if x<=-1 and x>=1: return None suma=0 for n in range(1,N): suma+=(-1)**(n+1)*(x**n)/n return suma # In[12]: # Ejemplo de uso x = 0.5 # Debe estar en (-1, 1] N = 10 aprox_ln = approx_ln(x, N) real_ln = math.log(1 + x) print(f"Aproximación de ln(1 + {x}) con {N} términos: {aprox_ln}") print(f"Valor real de ln(1 + {x}): {real_ln}") print(f"Diferencia: {abs(real_ln - aprox_ln)}") # # Números amigos en un rango dado # # Dos números naturales $a$ y $b$ se llaman **números amigos** si la suma de los divisores propios (excluyendo el número mismo) de $a$ es igual a $b$, y viceversa. # # Por ejemplo, 220 y 284 son números amigos porque: # - Los divisores propios de 220 son: 1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110 → suma: 284 # - Los divisores propios de 284 son: 1, 2, 4, 71, 142 → suma: 220 # # Escribe un programa que encuentre todos los pares de números amigos en un rango dado (por ejemplo, entre 1 y 10000). # In[13]: def suma_divisores_propios(n): """Calcula la suma de los divisores propios de un número (excluyendo al mismo número)""" if n == 1: return 0 suma = 1 # 1 es divisor propio para todos los números > 1 for i in range(2, n-1): if n % i == 0: suma += i return suma # In[14]: def encontrar_numeros_amigos(limite_inferior, limite_superior): """Encuentra todos los pares de números amigos dentro del rango especificado""" pares_amigos = set() for a in range(limite_inferior, limite_superior + 1): b = suma_divisores_propios(a) # Verificamos si b está en el rango y si la suma de divisores de b es igual a a if (limite_inferior <= b <= limite_superior and suma_divisores_propios(b) == a): pares_amigos.add((a, b)) return sorted(pares_amigos) # In[15]: # Definir el rango print("Buscador de números amigos") lim_inf = 1 lim_sup=10000 # Encontrar y mostrar los pares de números amigos pares = encontrar_numeros_amigos(lim_inf, lim_sup) if pares: print("\nPares de números amigos encontrados:") for par in pares: print(f"{par[0]} y {par[1]}") else: print("\nNo se encontraron pares de números amigos en el rango especificado.") # ## Actividad: # - Vemos que estamos obteniendo números duplicados. ¿Qué se puede hacer para evitar esto? # ## Una solución: # In[ ]: def encontrar_numeros_amigos(limite_inferior, limite_superior): """Encuentra todos los pares de números amigos dentro del rango especificado""" pares_amigos = set() for a in range(limite_inferior, limite_superior + 1): b = suma_divisores_propios(a) # Verificamos si b está en el rango, si la suma de divisores de b es igual a a y si b es mayor que a if (limite_inferior <= b <= limite_superior and suma_divisores_propios(b) == a and b>a): pares_amigos.add((a, b)) return sorted(pares_amigos) # In[17]: # Definir el rango print("Buscador de números amigos") lim_inf = 1 lim_sup=10000 # Encontrar y mostrar los pares de números amigos pares = encontrar_numeros_amigos(lim_inf, lim_sup) if pares: print("\nPares de números amigos encontrados:") for par in pares: print(f"{par[0]} y {par[1]}") else: print("\nNo se encontraron pares de números amigos en el rango especificado.") # ## Reto: # - ¿Alguna forma de reducir el tiempo de código? # Pista: La función `suma_divisores_propios` se puede optimizar # ## Una forma (se puede optimizar más) # In[18]: def suma_divisores_propios(n): """Calcula la suma de los divisores propios de un número (excluyendo al mismo número)""" if n == 1: return 0 suma = 1 # 1 es divisor propio para todos los números > 1 for i in range(2, int(n/2)+1): if n % i == 0: suma += i return suma