2.5.1 Secante Ejemplo01

Ejemplo 1 (Burden ejemplo 1 p.51/pdf.61)

La ecuación mostrada tiene una raiz en el intervalo [1,2], ya que

f(1) = -5
f(2) = 14

Muestre los resultados parciales del algoritmo de la secante con una tolerancia de 0.0001

f(x) = x^3 + 4x^2 -10 =0

[xa ,	 xb , 	 xc , 	 tramo]
[ 1.5     1.504   1.3736  0.1264]
[ 1.3736  1.5     1.3658  0.0078]
[  1.3658e+00   1.3736e+00   1.3652e+00   5.2085e-04]
raiz en:  1.36523214292

El algoritmo a implementar es:

# Método de la secante
# Ejemplo 1 (Burden ejemplo 1 p.51/pdf.61)
import numpy as np

def secante_tabla(fx,xa,tolera):
    dx = 4*tolera
    xb = xa + dx
    tramo = dx
    tabla = []
    while (tramo>=tolera):
        fa = fx(xa)
        fb = fx(xb)
        xc = xa - fa*(xb-xa)/(fb-fa)
        tramo = abs(xc-xa)
        
        tabla.append([xa,xb,xc,tramo])
        xb = xa
        xa = xc

    tabla = np.array(tabla)
    return(tabla)

# PROGRAMA ####################
# INGRESO
fx = lambda x: x**3 + 4*x**2 - 10

a = 1 ; b = 2
xa = 1.5
tolera = 0.001
tramos = 100

# PROCEDIMIENTO
tabla = secante_tabla(fx,xa,tolera)
n = len(tabla)
raiz = tabla[n-1,2]

# SALIDA
np.set_printoptions(precision=4)
print('[xa ,\t xb , \t xc , \t tramo]')
for i in range(0,n,1):
    print(tabla[i])
print('raiz en: ', raiz)

En el caso de añadir la gráfica para la primera iteración:

# GRAFICA
import matplotlib.pyplot as plt

# Calcula los puntos a graficar
xi = np.linspace(a,b,tramos+1)
fi = fx(xi)
dx = (b-xa)/2
pendiente = (fx(xa+dx)-fx(xa))/(xa+dx-xa)
b0 = fx(xa) - pendiente*xa
tangentei = pendiente*xi+b0
fxa = fx(xa)
xb = xa+dx
fxb = fx(xb)

plt.plot(xi,fi, label='f(x)')

plt.plot(xi,tangentei, label='secante')
plt.plot(xa,fx(xa),'go', label='xa')
plt.plot(xa+dx,fx(xa+dx),'ro', label='xb')
plt.plot((-b0/pendiente),0,'yo', label='xc')

plt.plot([xa,xa],[0,fxa],'m')
plt.plot([xb,xb],[0,fxb],'m')

plt.axhline(0, color='k')
plt.title('Método de la Secante')
plt.legend()
plt.grid()
plt.show()

Scipy.optimize.newton – Secante

El método de la secante se encuentra implementado en Scipy en la forma de algoritmo de newton, que al no proporcionar la función para la derivada de f(x), usa el método de la secante:

>>> import scipy.optimize as opt
>>> opt.newton(fx,xa, tol=tolera)
1.3652320383201266

https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.newton.html


Tarea: convertir el algoritmo a una función de python con respuesta simple

2.3.1 Newton-Raphson Ejemplo01

Referencia: Burden ejemplo 1 p.51/pdf.61

La ecuación mostrada tiene una raiz en [1,2], ya que f(1)=-5 y f(2)=14.
Muestre los resultados parciales del algoritmo de Newton Raphson con una tolerancia de 0.0001

f(x) = x^3 + 4x^2 -10 =0
['xi', 'xnuevo', 'tramo']
[ 2.   1.5  0.5]
[ 1.5     1.3733  0.1267]
[ 1.3733  1.3653  0.0081]
[  1.3653e+00   1.3652e+00   3.2001e-05]
raiz en:  1.3652300139161466

El algoritmo usado requiere desarrollar una parte analítica si la función es de tipo numérica, pues requiere encontrar la derivada de la función:

f(x) = x^3 + 4x^2 -10 f'(x) = 3x^2 + 8x

resultados, que añadiendo el punto inicial de análisis y la tolerancia permiten usar el algoritmo:

# Método de Newton-Raphson
# Ejemplo 1 (Burden ejemplo 1 p.51/pdf.61)

import numpy as np

# INGRESO
fx = lambda x: x**3 + 4*x**2 - 10
dfx = lambda x: 3*(x**2) + 8*x

x0 = 2
tolera = 0.001

# PROCEDIMIENTO
tabla = []
tramo = abs(2*tolera)
xi = x0
while (tramo>=tolera):
    xnuevo = xi - fx(xi)/dfx(xi)
    tramo = abs(xnuevo-xi)
    tabla.append([xi,xnuevo,tramo])
    xi = xnuevo

tabla = np.array(tabla)
n=len(tabla)

# SALIDA
print(['xi', 'xnuevo', 'tramo'])
np.set_printoptions(precision = 4)
for i in range(0,n,1):
    print(tabla[i])
print('raiz en: ', xi)

scipy.optimize.newton

El método de Newton-Raphson se encuentra implementado en Scipy, que también puede ser usado de la forma:

>>> import scipy.optimize as opt
>>> opt.newton(fx,x0, fprime=dfx, tol = tolera)
1.3652300139161466
>>> 

https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.newton.html


Ejemplo

Calcule la raíz de f(x) = e-x – x, empleando como valor inicial x0 = 0

Tarea

  • convertir el algoritmo a una función,
  • Revisar las modificaciones si se quiere usar la forma simbólica de la función.

2.4.1 Posición Falsa Ejemplo01

Referencia: Burden ejemplo 1 p.51/pdf.61

La ecuación mostrada tiene una raiz en [1,2], ya que f(1)=-5 y f(2)=14. Muestre los resultados parciales del algoritmo de la posición falsa con una tolerancia de 0.0001

f(x) = x^3 + 4x^2 -10 =0

Algoritmo:

# Algoritmo de falsa posicion para raices
# Los valores de [a,b] son seleccionados
# desde la gráfica de la función
# error = tolera

import numpy as np

def posicionfalsa_tabla(fx,a,b,tolera):
    fa = fx(a)
    fb = fx(b)
    c = b - fb*(a-b)/(fa-fb)
    fc = fx(c)
    tramo = abs(c-a)
    
    tabla = [[a,c,b,fa, fc, fb, tramo]]
    while (tramo > tolera):
        
        cambia = np.sign(fa)*np.sign(fc)
        if (cambia > 0):
            tramo = abs(c-a)
            a=c
        else:
            tramo = abs(b-c)
            b=c
        fa = fx(a)
        fb = fx(b)
        c = b - fb*(a-b)/(fa-fb)
        fc = fx(c)

        tabla.append([a,c,b,fa, fc, fb, tramo])
        
    tabla = np.array(tabla)
    
    return(tabla)


# PROGRAMA ############################
# INGRESO
fx = lambda x: x**3 + 4*x**2 - 10

a = 1 ; b = 2
tolera = 0.001
tramos = 100

# PROCEDIMIENTO
tabla = posicionfalsa_tabla(fx,a,b,tolera)
n=len(tabla)
raiz = tabla[n-1,1]

xi = np.linspace(a,b,tramos+1)
fi = fx(xi)
pendiente = (fx(b)-fx(a))/(b-a)
desde = fx(a) - pendiente*a
gi = desde + pendiente* xi 


# SALIDA
np.set_printoptions(precision=4)
for i in range(0,n,1):
    print('i =  ',i)
    print('   [a,c,b]: ', tabla[i,0:3])
    print('[fa,fc,fb]: ', tabla[i,3:6])
    print('     tramo: ', tabla[i,6]) 
print('raiz:', raiz)

Observe el número de iteraciones realizadas.
Resultado:

i =   0
   [a,c,b]:  [ 1.      1.2632  2.    ]
[fa,fc,fb]:  [ -5.      -1.6023  14.    ]
     tramo:  0.263157894737
i =   1
   [a,c,b]:  [ 1.2632  1.3388  2.    ]
[fa,fc,fb]:  [ -1.6023  -0.4304  14.    ]
     tramo:  0.075669944091
i =   2
   [a,c,b]:  [ 1.3388  1.3585  2.    ]
[fa,fc,fb]:  [ -0.4304  -0.11    14.    ]
     tramo:  0.0197185029969
i =   3
   [a,c,b]:  [ 1.3585  1.3635  2.    ]
[fa,fc,fb]:  [ -0.11    -0.0278  14.    ]
     tramo:  0.00500109821731
i =   4
   [a,c,b]:  [ 1.3635  1.3648  2.    ]
[fa,fc,fb]:  [ -2.7762e-02  -6.9834e-03   1.4000e+01]
     tramo:  0.00125959178469
i =   5
   [a,c,b]:  [ 1.3648  1.3651  2.    ]
[fa,fc,fb]:  [ -6.9834e-03  -1.7552e-03   1.4000e+01]
     tramo:  0.000316686057598
raiz: 1.36512371788
>>> 

Ejemplo 2 (Burden ejemplo 3 p.74/pdf.84)

Con el método de la posición falsa, determine la cantidad de iteraciones necesarias para resolver:

f(x) = \cos (x) - x

Realice una tabla que muestre: [ i, a, b, c, f(c) ].
Seleccióne el rango [a,b] usando una gráfica y compruebe los resultados.
Compare con otros métodos para encontrar raíces.

2.2.1 Punto fijo – Ejemplo01

Ejemplo 1:

f(x):e^{-x} - x = 0

Desarrollo: Al igual que los métodos anteriores, es conveniente determinar el rango donde la función es válida [a,b], revisar si hay cambio de signo para buscar una raiz. Para el ejemplo, el rango de estudio será [0,1], pues f(0)=1 es positivo y f(1)=-0.63 es negativo.

Para el punto fijo, se reordena la ecuación para para tener una ecuación con la variable independiente separada. Se obtiene por un lado la recta identidad y=x, por otro se tiene la función g(x) y se buscará la intersección entre las dos .

x = e^{-x} g(x) = e^{-x}

Se puede iniciar la búsqueda por uno de los extremos del rango [a,b]. Por ejemplo:

  • iniciando desde el extremo izquierdo a,
  • se determina el valor de b = g(a) ,
  • se determina la diferencia de aproximaciones como
    el error = |b-a|
  • se proyecta en la recta identidad, que sirve como el nuevo punto de evaluación
    a=b.
  • se repite el proceso para el nuevo valor de b, hasta que el error sea menor al tolerado.
  • En caso que el proceso no converge, se utiliza un contador de iteraciones máximo, para evitar tener un lazo infinito.

El proceso se resume en la gráfica, para una función g(x) que converge.


El algoritmo en python se presenta como una función para usarla fácilmente como un bloque en otros ejercicios. Se requiere la función gx, el punto inicial y la tolerancia, la variable de número de iteraciones máxima n es opcional.

# Algoritmo de punto fijo
# [a,b] son seleccionados desde
# la gráfica de la función
# error = tolera

import numpy as np
def puntofijo(gx,a,tolera, n = 15):
    """
    g(x) se obtiene al despejar una x de f(x)
    máximo de iteraciones predeterminado: n
    si no converge hasta n iteraciones
    la respuesta es NaN (Not a Number)
    """
    i = 1
    b = gx(a)
    tramo = abs(b-a)
    while(tramo>=tolera and i<=n):
        a = b
        b = gx(a)
        tramo = abs(b-a)
        i = i+1
    respuesta = b
    # Valida respuesta
    if (i>=n):
        respuesta = np.nan
    return(respuesta)


# PROGRAMA #######################
# INGRESO
fx = lambda x: np.exp(-x) - x
gx = lambda x: np.exp(-x)

a = 0 ; b = 1
tolera = 0.001
tramos = 101

# PROCEDIMIENTO
respuesta = puntofijo(gx,a,tolera)

# SALIDA
print(respuesta)

la respuesta obtenida del problema es

0.566908911921

Para obtener la gráfica básica se determinan los puntos para cada función fx y gx. Se añaden las siguiente instrucciones al algoritmo anterior:

# GRAFICA
# calcula los puntos para fx y gx
xi = np.linspace(a,b,tramos)
fi = fx(xi)
gi = gx(xi)
yi = xi

import matplotlib.pyplot as plt
plt.plot(xi,fi, label='f(x)')
plt.plot(xi,gi, label='g(x)')
plt.plot(xi,yi, label='y=x')

plt.axvline(respuesta)
plt.axhline(0, color='k')
plt.title('Punto Fijo')
plt.legend()
plt.show()

Scipy.optimize.fixed_point

El método del punto fijo se encuentra implementado en Scipy, que también puede ser usado de la forma:

>>> import scipy.optimize as opt
>>> opt.fixed_point(gx,a,xtol=0.001,maxiter=15)
array(0.5671432948307147)

el valor predeterminado de iteraciones si no se escribe es 500 y la tolerancia predeterminada es xtol=1e-08
https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fixed_point.html


Tarea

  • Revisar lo que sucede cuando el valor inicial a esta a la derecha de la raiz.
  • Validar que la función converge, revisando que |g'(x)|<1, o que la función g(x) tenga pendiente menor a pendiente de la recta identidad.
  • Realizar el mismo ejercicio para
f(x) = x^{2}-x-2 = 0

en el rango [-1,2]
Realice sus observaciones y recomendaciones.

2.1.1 Bisección Ejemplo01

Referencia: Burden ejemplo 1 p.51/pdf.61

La ecuación mostrada tiene una raiz en [1,2], ya que f(1)=-5 y f(2)=14 y existe cambio de signo.
Muestre los resultados parciales del algoritmo de la bisección con una tolerancia de 0.0001

f(x) = x^3 + 4x^2 -10 =0

Desarrollo en Python

Observe los resultados de f(c), principalmente en la iteracion 9, respecto a la obtenida en la última posición.

[ i, a, c, b, f(a), f(c), f(b), paso]
1 1.000 1.500 2.000 -5.000 2.375 14.000 1.000 
2 1.000 1.250 1.500 -5.000 -1.797 2.375 0.500 
3 1.250 1.375 1.500 -1.797 0.162 2.375 0.250 
4 1.250 1.312 1.375 -1.797 -0.848 0.162 0.125 
5 1.312 1.344 1.375 -0.848 -0.351 0.162 0.062 
6 1.344 1.359 1.375 -0.351 -0.096 0.162 0.031 
7 1.359 1.367 1.375 -0.096 0.032 0.162 0.016 
8 1.359 1.363 1.367 -0.096 -0.032 0.032 0.008 
9 1.363 1.365 1.367 -0.032 0.000 0.032 0.004 
10 1.363 1.364 1.365 -0.032 -0.016 0.000 0.002 
11 1.364 1.365 1.365 -0.016 -0.008 0.000 0.001 
raiz:  1.36474609375
>>> 

se grafican los puntos c de la tabla para obsevar mejor el resultado. Para la gráfica se requieren ordenar los puntos c.

Escriba sus observaciones y preguntas sobre los resultados.

Los resultados se obtienen usando un algoritmo modificado de la bisección, para agregar los resultados parciales a una tabla y mostrar el resultado:

# Algoritmo de Bisección
# [a,b] se escogen de la gráfica de la función
# error = tolera

import numpy as np

fx = lambda x: x**3 + 4*x**2 - 10

# INGRESO
a = 1
b = 2
tolera = 0.001

# PROCEDIMIENTO
tabla = []
tramo = b-a

fa = fx(a)
fb = fx(b)
i = 1
while (tramo>tolera):
    c = (a+b)/2
    fc = fx(c)
    tabla.append([i,a,c,b,fa,fc,fb,tramo])
    i = i+1
                 
    cambia = np.sign(fa)*np.sign(fc)
    if (cambia<0):
        b = c
        fb = fc
    else:
        a=c
        fa = fc
    tramo = b-a
c = (a+b)/2
fc = fx(c)
tabla.append([i,a,c,b,fa,fc,fb,tramo])
tabla = np.array(tabla)

raiz = c

# SALIDA
np.set_printoptions(precision = 4)
print('[ i, a, c, b, f(a), f(c), f(b), paso]')
# print(tabla)

# Tabla con formato
n=len(tabla)
for i in range(0,n,1):
    unafila = tabla[i]
    formato = '{:.0f}'+' '+(len(unafila)-1)*'{:.3f} '
    unafila = formato.format(*unafila)
    print(unafila)
    
print('raiz: ',raiz)

para realizar la gráfica se áñade:

# GRAFICA
import matplotlib.pyplot as plt

xi = tabla[:,2]
yi = tabla[:,5]

# ordena los puntos para la grafica
orden = np.argsort(xi)
xi = xi[orden]
yi = yi[orden]

plt.plot(xi,yi)
plt.plot(xi,yi,'o')
plt.axhline(0, color="black")

plt.xlabel('x')
plt.ylabel('y')
plt.title('Bisección en f(x)')
plt.grid()
plt.show()

Scipy.optimize.bisect

El método de la bisección se encuentra implementado en Scipy, que también puede ser usado de la forma:

>>> import scipy.optimize as opt
>>> opt.bisect(fx,1,2,xtol=0.001)
1.3642578125

que es el valor de la variable ‘a’ de la tabla para la última iteración del ejercicio. Lo que muestra que el algoritmo realizado tiene un valor más aproximado.

https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.bisect.html

2.5 Secante – Concepto

Referencia: Burden 2.3 p.70/pdf.80, Chapra 6.3 p.154/pdf178

Un posible inconveniente en el método de Newton Raphson es implementar  evaluación de la derivada, ésta se puede aproximar mediante una diferencia finita dividida hacia atras:

f'(x_i) = \frac{f(x_{i-1})-f(x_i)}{x_{i-1}-x_i}

la que se sustituye en la ecuación del método de Newton-Raphson para obtener:

x_{i+1}= X_i - \frac{f(x_i)(x_{i-1} - x_i)}{f(x_{i-1}) - f(x_i)}

Observación: ¿Cuál es la diferencia con el método de Newton-Raphson?

2.3 Newton-Raphson – Concepto

Referencia: Burden 2.3 p.66/pdf.76, Chapra 6.2 p.148/pdf172, Rodriguez 3.3 p.52

Se deduce a partir de la interpretación gráfica o por medio del uso de la serie de Taylor.

De la gráfica, se usa el triángulo formado por la recta tangente que pasa por f(xi), con pendiente f'(xi)  y el eje x.

f'(x_i) = \frac{f(x_i) - 0}{x_i - x_{i+1}}

El punto xi+1 es la intersección de la recta tangente con el eje x, que es más cercano a la raíz de f(x), valor que es usado para la próxima iteración. Reordenando la ecuación de determina la fórmula para el siguiente punto:

x_{i+1} = x_i -\frac{f(x_i)}{f'(x_i)}

El error se determina como la diferencia entre los valores sucesivos encontrados |xi+1 – xi|

Tarea: Use la serie de Taylor hasta la primera derivada para encontrar el siguiente punto de aproximación xi+1

2.2 Punto fijo – Concepto

Referencia: Burden 2.2 p.55/pdf.65, Chapra 6.1 p.143/pdf167, Rodriguez 3.2 p.44

Es un método abierto, también llamado de iteración de un punto o sustitución sucesiva, que reordena la ecuación

f(x)=0

de la forma en que x esté del lado izquierdo de la ecuación, para buscarla intersección entre la recta identidad y la curva g(x), como se muestran en los siguientes ejemplos.

x=g(x)

Ejemplo 1:

f(x):e^{-x} - x = 0

se reordena para tener:

x = e^{-x} g(x) = e^{-x}

 

Ejemplo 2: 

f(x): x^2 - 2x -3 = 0

se reordena para tener:

x = \frac {x^2 - 3}{2} g(x) = \frac {x^2 - 3}{2}

 

Ejemplo 3:

f(x): \sin (x) = 0

puede ser complicado despejar x, por lo que se simplifica el proceso sumando x en ambos lados.

x = \sin (x) + x g(x) = \sin (x) + x

El método proporciona una fórmula para predecir un valor nuevo de x en función del valor anterior:

x_{i+1} = g(x_i)

con error aproximado calculado como:

\epsilon_a = \left| \frac{x_{i+1} - x_i}{x_{i+1}} \right| 100\%

Desarrolle un algoritmo para el método.

  • ¿cuál sería el valor de tolerancia?
  • ¿parámetros de inicio?
  • compare con el resultado de otros métodos.
  • Revisar el resultado cuando no se cumple que |g'(x)|<1

2.4 Posición Falsa – Concepto

Referencia: Burden p.72/pdf.82, Chapra 5.3 p.131/pdf155

El método de la posición falsa considera dividir el intervalo cerrado [a,b] donde se encontraría una raíz de la función f(x) basado en la cercanía a cero que tenga f(a) o f(b).

El método une f(a) con f(b) con una línea recta, la intersección de la línea con el eje x representaría una mejor aproximación de la raiz.

Al reemplazar la curva de f(x) por una línea recta, se genera el nombre de «posición falsa» de la raíz.

El método también se conoce como interpolación lineal.

A partir de la gráfica, usando triángulos semejantes se estima que:

\frac{f(a)}{c-a} = \frac{f(b)}{c-b}

que al despejar c, se obtiene:

c = b - f(b) \frac{(a-b)}{f(a)-f(b)}

Calculado el valor de c, éste reemplaza a uno de los valores iniciales [a,b], cuyo valor evaluado tenga el mismo signo que f(c)

Nota: La forma de la expresión presentada para c, se usa para comparar con el método de la secante. Se obtiene sumando y restando b y reagrupando.


Algoritmo propuesto para análisis y mejoras:

# Algoritmo de falsa posicion para raices
# Los valores de [a,b] son seleccionados
# desde la gráfica de la función
# error = tolera

import numpy as np

def posicionfalsa(fx,a,b,tolera):
    fa = fx(a)
    fb = fx(b)
    c = b - fb*(a-b)/(fa-fb)
    
    tramo = abs(c-a)
    while (tramo > tolera):
        fc = fx(c)
        cambia = np.sign(fa)*np.sign(fc)
        if (cambia > 0):
            tramo = abs(c-a)
            a=c
            fa=fc
        else:
            tramo = abs(c-b)
            b=c
            fb=fc
        c = b - fb*(a-b)/(fa-fb)
        
    respuesta = c
    
    # Valida respuesta
    fa = fx(a)
    fb = fx(b)
    cambio = np.sign(fa)*np.sign(fb)
    if (cambio>0):
        respuesta = np.nan
        
    return(respuesta)

 

2.1 Bisección – Concepto

Referencia: Burden 2.1 p.48/pdf.58, Chapra 5.2 p.124/pdf148, Rodriguez 3.1 p.36

El método se basa en el teorema del valor intermedio, conocido como método de la bisección, busqueda binaria, partición de intervalos o de Bolzano.

Es un tipo de búsqueda incremental en el que:

  • el intervalo se divide siempre en la mitad.
  • Si la función cambia de signo sobre un intervalo, se evalua el valor de la función en el punto medio.
  • La posición de la raíz se determina en el punto medio del subintervalo  dentro del cual ocurre un cambio de signo.
  • el proceso se repite hasta obtener una mejor aproximación

Cota de Error

Teorema 2.1 (Burden p,52/pdf.62.)

Suponga que f ∈ C[a,b] y f(a)*f(b)<0, f es una función en el intervalo [a,b] y que presenta un cambio de signo.

|p_n - p| \leq \frac{b-a}{2^n} , \text{donde } n \geq 1

la desigualdad implica que pn converge a p con una razón de convergencia O \big(\frac{1}{2^n}\big) , es decir:

p_n =p+O \Big( \frac{1}{2^n} \Big)

Iteraciones, Ejemplo 2 (Burden ejemplo 2 p.52/pdf.62)

Determine la cantidad de iteraciones necesarias para resolver f(x) = x^3 + 4x^2 -10 =0 con exactitud de 10 – 3 en el intervalo [1,2].

Desarrollo: Se buca encontrar un entero n que satisface la ecuación:

|p_n -p| \leq \frac{b-a}{2^{n}} 2^{-n}< 10^{-3}

usando logaritmos:

-n log_{10} 2 < -3 n > \frac{3}{log_{10} 2} = 9.96

En consecuencia se requieren unas diez iteraciones para lograr la aproximación de 10-3. Verifique los resultados con los valores calculados.


Se presenta una forma de implementar el algoritmo de la bisección:

# Algoritmo de Bisección
# Los valores de [a,b] son seleccionados
# desde la gráfica de la función
# error = tolera

import numpy as np

def biseccion(fx,a,b,tolera):

    fa = fx(a)
    fb = fx(b)
   
    tramo = np.abs(b-a)
    while (tramo>=tolera):
        c = (a+b)/2
        fc = fx(c)
        cambia = np.sign(fa)*np.sign(fc)
        if (cambia<0):
            b = c
            fb = fc
        else:
            a = c
            fa = fc
        tramo = np.abs(b-a)
       
    return(c)