import math
import matplotlib.pyplot as plt
import numpy as np

def exp(x, n):
    somma = 1.0
    xk = 1.0
    fatt = 1
    for k in range(1, n + 1):
        xk*= x
        fatt*= k
        somma+= xk/fatt
    return somma

def f(x):
    return x**3 - x**2 - x - 1

def f1(x):
    return 3*x**2 - x*x - 1

# ESERCIZIO 1
x = 1
y0 = math.e**x
y1 = exp(x, 4)
err = 100*abs(y1 - y0)/y0
print("e^", x, " in Python:", y0)
print("e^", x, " con la funzione propria:", y1)
print("Errore relativo:", err)

# ESERCIZIO 2
xMin = -4
xMax = 4
x = np.linspace(xMin, xMax, num = 200, endpoint = True)
y1 = x**3
y2 = x**2 + x + 1
plt.plot(x, y1, color = "tab:blue")
plt.plot(x, y2, color = "tab:orange")
plt.grid()
plt.show()
x0 = 2    # Punto iniziale del metodo di Newton
print("x0 =", x0)
xOld = 1000
xNew = x0 # Valore molto grande per poter iniziare
tol = 1e-5 # Tolleranza
it = 1
while abs(xNew - xOld) >= tol:
    xOld = xNew
    xNew = xOld - f(xOld)/f1(xOld)
    print("Iterazione", it, "x =", xNew)
    it+= 1
print("")
print("VERIFICA FINALE")
print("f(%.6f) = %.6f" % (xNew, f(xNew)))
