# -*- coding: cp1252 -*-
from math import *

'''
Comentario: recuerden que el metodo de la bisección lo que busca es encontrar una aproximación
para el valor de una raiz de una función, es decir, si nuestra función fuera f(x)=x^2-1,
y queremos ver una raiz en el intervalo [0 , 3], muy probablemente con el metodo de la biseccion
no lleguemos a que nuestra raiz sea 1, si no que llegaremos a que nuestra raiz es 0.998465 o algo similar.
Por lo que no podemos exigirle en nuestro codigo que haya una igualdad exactamente 0.
Asi que nos relejaremos y simplemente pediremos que sea, en valor absoluto,
menor a un valor cercano a 0, que lo llamaremos aca epsilon, en este caso le pondre 0.0001, ustedes pueden cambiarlo
Entre más cercano a 0 el valor de epsilon más preciso será el valor resultante, pero se demorará más
'''
epsilon=0.0001 #esto es una variable global


#f: double -> double
#entrega el resultado de evaluar el valor x en una expresion que representa a una funcion de variable real, en este caso lo voy a dejar en tan(x)-x pero ustedes pueden cambiarlo
#ej: tan(pi)-pi retorna -pi
def f(x):
    #la siguiente expresión puedes modificarla, por ejemplo si se pone x**(2)-1
    return tan(x)-x

#biseccion: double,double -> double
#Entrega el valor de la raiz usando el metodo de la biseccion estudiada en el curso MA-1002
#ej: bieccion(4.4,4.5) retorna 4.4934...
def biseccion(a,b):
    numero_intervalo=0
    if f(a)==0:
        print "se encontro raiz en la frontera "+str(a)
        return a
    if f(b)==0:
        print "se encontro raiz en la frontera "+str(b)
        return b
    if f(a)*f(b)>0:
        print "no es posible aplicar en este intervalo el metodo de la biseccion, asuma nuevos valores para a y b"
        return
    else: #caso cuando f(a)*f(b)<=0
        print "intervalo "+str(numero_intervalo)+" = ["+str(a)+","+str(b)+"]"
        while((b-a)>=epsilon):
            c=(a+b)/2.0
            print "el valor de c es "+str(c)
            print "-----------------------------------------------------------"
            numero_intervalo+=1
            if f(a)*f(c)<=0:
                b=c
            else:
                a=c          
            print "intervalo "+str(numero_intervalo)+" = ["+str(a)+","+str(b)+"]"
    print "los valores de la frontera del intervalo "+str(numero_intervalo) +" son casi iguales, el algoritmo debe terminar"
    print "..."
    print "el valor aproximado de la raiz es "+str(c)
    return c


''' De ahora en adelante esto viene siendo una pseudo-aplicacion '''

print "ahora se calculara para la función f(x)=tan(x)-x, su raiz en el intervalo [4.4 , 4.5] con una tolerancia de 0.0001"
print "con esto se logra obtener un resultado con 4 decimales exactos, esto puede ser modificado. (si se usa 0.0000001, se obtiene el resultado del apunte)"
print ""
resultado=biseccion(4.4,4.5)

