Anda di halaman 1dari 9

PONTIFICIA UNIVERSIDAD CATÓLICA DE CHILE

ESCUELA DE INGENIERÍA
DEPARTAMENTO DE CIENCIA DE LA COMPUTACIÓN
IIC 1102 INTRODUCCIÓN A LA PROGRAMACIÓN
Profesor: Rodrigo Sandoval U.

Capítulo VI – Algoritmos Numéricos

1 ALGORITMOS O MÉTODOS NUMÉRICOS................................................................................................. 1


1.1 EJEMPLO: CÁLCULO DE E MEDIANTE SERIE INFINITA ...................................................................................... 1
1.2 EJEMPLO: CÁLCULO DE E A LA X, MEDIANTE SERIE, COMPARANDO CON FUNCIÓN EXP() ................................ 2
1.3 EJEMPLO: CÁLCULO DE A ELEVADO A LA X (A**X), MEDIANTE SERIES, CON LA MÁXIMA PRECISIÓN POSIBLE 4
1.4 EJEMPLO: MÉTODO DE NEWTON PARA ENCONTRAR CEROS DE FUNCIONES .................................................... 6
1.4.1 Implementación ...................................................................................................................................... 7

Material preparado por Rodrigo Sandoval U en Marzo 2004,


basado en los apuntes de clase del curso IIC1102, año 2003, de M. Nussbaum, Marcos Sepúlveda, et.al
Los ejemplos fueron preparados por el MSR Lab del Depto de Ciencia de la Computación, Escuela de Ingeniería
Intro. Prog. Orientada a Objeto – Algoritmos Numéricos Rodrigo Sandoval U.

1 Algoritmos o Métodos Numéricos

Los métodos numéricos permiten resolver problemas obteniendo aproximaciones para las
soluciones mediante algoritmos iterativos.
Estos algoritmos reciben el nombre de algoritmos numéricos.
Las aproximaciones resultan de mucha utilidad cuando las soluciones analíticas o algebraicas resultan
muy difíciles o hasta imposibles de obtener empleando métodos tradicionales. Los computadores ayudan
en gran manera, al facilitar la programación de los algoritmos basados en iteración.
En esta sección se presentan ejemplos de estos métodos.

1.1 Ejemplo: Cálculo de e mediante serie infinita


Programa que calcula el valor de la constante e, base de los logaritmos neperianos. Se hace una
aproximación empleando la siguiente serie infinita:
e = 1 + 1/1! + 1/2! + 1/3! + 1/4! + ...
El cálculo se detiene cuando el valor acumulado de e, no se logra diferenciar (por la precisión del
computador), del valor calculado en la iteración anterior. Es decir, cuando el siguiente término a sumar es
tan pequeño que el computador lo considera como un cero.
El factorial, representado por ! en la serie, se implementa en el programa mediante una función.
Una vez que se calcula la aproximación, el programa despliega el valor encontrado, así como el número
de iteraciones que se emplearon para obtenerlo, es decir, la cantidad de términos de la serie que fue
necesario sumar para llegar a la aproximación.

/***************************************************************************
* Ejemplo: Calculo de la constante e mediante una serie infinita
***************************************************************************/

using System;

/***************************************************************************
* Función que calcula el factorial de su argumento. Tanto el argumento de
* entrada (x) como el valor de retorno son de tipo double. No se hacen
* controles sobre la validez del argumento, cuyo valor debe ser > 0.
* Cualquier valor de entrada 0 o negativo arrojara un resultado de 1.
* Formula del factorial: x! = 1 * 2 * 3 * ... * (x-1) * x
***************************************************************************/
public class CCalculateE
{
public double iter;

public CCalculateE() { iter = 1; }

private double mFactorial(double x)


{
double i; // Factor actual de multiplicación: 2, 3, ..., x
double fact = 1.0; // Acumulador para el resultado, inicialmente 1

// Ciclo en el que se calcula el factorial: i variara de 2 a x


for (i=2.0; i<=x; i++)
// Se multiplica el acumulado actual por el factor actual (i)
fact = fact * i;

// Devuelve como valor de retorno el resultado acumulado


return(fact);
}

public double mGetE()


{

IIC 1102 Página: 1


Intro. Prog. Orientada a Objeto – Algoritmos Numéricos Rodrigo Sandoval U.

double e = 1,
eanterior;

do{
eanterior = e;
e += 1/mFactorial(iter);
iter++;
}while( e != eanterior);

return e;
}
}
/***************************************************************************
* Programa que calcula el valor de la constante e, base de los logaritmos
* neperianos. Se emplea una aproximación de la siguiente serie infinita:
* e = 1 + 1/1! + 1/2! + 1/3! + 1/4! + ...
* El cálculo se detiene cuando el valor acumulado de e, no se logra
* diferenciar (por la precisión del computador), del valor calculado
* en la iteración anterior.
***************************************************************************/
public class CMain
{
public static void Main()
{
CCalculateE ce = new CCalculateE();

Console.WriteLine("El valor de E es: {0}",ce.mGetE());


Console.WriteLine("Se emplearon {0} iteraciones.",ce.iter);
}
}

Ejemplo de ejecución:

Valor de e:
2.718281828459045534884808148490265011787000000000
Se emplearon 19 iteraciones

1.2 Ejemplo: Cálculo de e a la x, mediante serie, comparando con función exp()


Programa que calcula e**x (e elevado a la x), haciendo una aproximación mediante una serie infinita. Se
siguen sumando términos mientras la diferencia entre el valor aproximado y el valor devuelto por la
función exp() de la biblioteca math de C, sea mayor que una precisión dada por el usuario. La serie
empleada es:
Serie empleada: e**x = 1 + (x**1 / 1!) + (x**2 / 2!) + (x**3 / 3!) + ...
El factorial, representado por !, y el operador de potencia, representado por **, se implementan en el
programa mediante funciones.
Una vez obtenida la aproximación, el programa despliega el valor calculado, y el número de iteraciones
que se emplearon para llegar a él, es decir, el número de términos que fue necesario sumar.

/***************************************************************************
* Ejemplo: Calculo de e**x (e elevado a la x), empleando serie infinita *
***************************************************************************/
using System;

public class CEelevadoX


{
public double iter;
public double res;
public double exacto;
public double precision;

IIC 1102 Página: 2


Intro. Prog. Orientada a Objeto – Algoritmos Numéricos Rodrigo Sandoval U.

// Constructor de la clase CEelevadoX


public CEelevadoX(double pres)
{
precision = pres;
iter = 1;
res = 1;
}
// Miembro privado ya que solo se usa dentro de la clase
private double mFactorial(double x)
{
double i;
double fact = 1;

for (i=2.0; i<=x; i++) fact = fact * i;

return(fact);
}

// Miembro privado ya que solo se usa dentro de la clase


private double mPotencia(double x, double n)
{
double i;
double pot;

pot = x;

for (i=2; i<=n; i++) pot = pot * x;

return(pot);
}

// Miembro público ya que se llama desde afuera de la clase para calcular e**x
public double mGetEX(double power)
{
exacto = Math.Exp(power);

do {
res += mPotencia(power,iter)/mFactorial(iter);
iter++;
} while((exacto - res) >= precision);

return res;
}
}

public class CMain


{
public static void Main()
{
double pres,x;

Console.Write("Ingrese la potencia: ");


x = Double.Parse(Console.ReadLine());
Console.Write("Ingrese la precisión: ");
pres = Double.Parse(Console.ReadLine());

// Nueva instancia de la clase CEelevadoX


CEelevadoX ex = new CEelevadoX(pres);
ex.mGetEX(x);

Console.WriteLine("El valor de e^x de System.Math es: {0}",ex.exacto);


Console.WriteLine("El valor de e^x con {0} iteraciones y precisión de {1} es: {2}",
ex.iter,ex.precision,ex.res);
}
}

IIC 1102 Página: 3


Intro. Prog. Orientada a Objeto – Algoritmos Numéricos Rodrigo Sandoval U.

Ejemplo de ejecución:

Ingrese el valor de x: 5
Ingrese la precision para el calculo de e(x): 0.01

Valor exp(x) de <math.h>: 148.413159102576600000000000000000000000000000000000

Calculo de e(x) con precision 1.000000e-002:


148.410210275043060000000000000000000000000000000000
Se emplearon 17 iteraciones

Ingrese el valor de x: 5
Ingrese la precision para el calculo de e(x): 0.000001

Valor exp(x) de <math.h>: 148.413159102576600000000000000000000000000000000000

Calculo de e(x) con precision 1.000000e-006:


148.413158521647740000000000000000000000000000000000
Se emplearon 23 iteraciones

1.3 Ejemplo: Cálculo de a elevado a la x (a**x), mediante series, con la máxima


precisión posible
Programa que calcula a**x (a elevado a la x), haciendo una aproximación mediante una serie, con la
máxima precisión que el lenguaje C puede calcular, esto es, hasta que los resultados alcanzados por la
serie converjan en un mismo valor. Se siguen calculando términos de la serie mientras no exista
diferencia entre un valor aproximado y el siguiente valor aproximado. La serie empleada es:
a**x = 1+x*logE(a)+((x*logE(a))**2)/2!+((x*logE(a))**3)/3! + ...
Elevar un número a una potencia, es representado en el texto por ** (lo cual no es una sintaxis válida en
C#).
Una vez obtenida la aproximación, el programa despliega el valor calculado.
// Cálculo de a elevado a la x (a**x) con la máxima precisión posible en C#.
// los valores de a y x deben ser mayores que cero
// se sabe que a**x = 1 + x * logE(a) + ((x * logE(a))**2)/2! + ((x * logE(a))**3)/3! + ...
// y que logE(x) = 2 [(x-1)/(x+1) + 1/3((x-1)/(x+1))**3 + 1/5((x-1)(x+1))**5 - ...
//
// Recuerde que: (a**n) = a * (a**(n-1))

using System;

public class CAElevadoX


{
private double mLogE(double x)
{
double basem,bas,res,resa,rep;

bas = (x-1.0)/(x+1.0);
basem = bas;
res = bas;
rep = 3.0;

do
{ resa = res;
basem = basem * bas * bas;
res = res + (1/rep)*basem;
rep += 2.0;
} while (res != resa);

return(2*res);
}

IIC 1102 Página: 4


Intro. Prog. Orientada a Objeto – Algoritmos Numéricos Rodrigo Sandoval U.

private double mFactorial(int x)


{
int i;
double fact = 1;

for (i=2; i<=x; i++) fact = fact * i;

return fact;
}

public double mPower(double a, double x)


{
double res,resa,bas,basem;
int rep;
bas = x * mLogE(a);
basem = bas;
rep = 2;
res = bas;

do
{
resa = res;
basem = basem * bas;
res += ( basem / mFactorial(rep) );
rep++;
} while (res != resa);

return(1+res);
}
}

public class CMain


{
public static void Main()
{
double a,x;

Console.Write("Ingrese la base: ");


a = Double.Parse(Console.ReadLine());
Console.Write("Ingrese la Potencia: ");
x = Double.Parse(Console.ReadLine());

CAElevadoX ax = new CAElevadoX();

Console.WriteLine("La respuesta es: {0}",ax.mPower(a,x));


}
}

Ejemplo de ejecución:

Introducir valores: 2 3
valores de a: 2.00000 y x: 3.00000
resultado 8.00000

IIC 1102 Página: 5


Intro. Prog. Orientada a Objeto – Algoritmos Numéricos Rodrigo Sandoval U.

1.4 Ejemplo: Método de Newton para encontrar ceros de funciones


Existen ecuaciones cuya solución mediante técnicas algebraicas tradicionales pueden resultar muy
difíciles de obtener. Un ejemplo es la ecuación:
ln x + 3x = 10.8074
Como se mencionó anteriormente, los métodos numéricos ofrecen una alternativa para resolver este tipo
de problemas, permitiendo obtener aproximaciones a las soluciones reales. En esta sección se presenta
un algoritmo que implementa el Método de Newton para encontrar soluciones a ecuaciones del tipo f (x)
= 0.
La función para la cual se quieren encontrar los ceros será definida mediante una directiva de
precompilación #define parametrizada, con lo cual ilustraremos la potencialidad de este tipo de
definiciones. El usuario debe suministrar una aproximación inicial de la solución, que llamaremos x1.
Entre más cercana esté esta aproximación inicial de la solución, más rápido llegará el programa a un
resultado. Nuestro algoritmo es iterativo, y se detiene cuando la diferencia entre dos aproximaciones
sucesivas está dentro de una precisión o tolerancia dada por el usuario. Es decir:

La fórmula básica empleada en el método de Newton para generar la siguiente aproximación para la
solución es:

El algoritmo que aquí se presenta hace también una aproximación numérica para la derivada f ' (x),
obteniendo entonces la siguiente ecuación:

IIC 1102 Página: 6


Intro. Prog. Orientada a Objeto – Algoritmos Numéricos Rodrigo Sandoval U.

1.4.1 Implementación
La función a la que se quiere encontrar el cero se define en el programa mediante la siguiente definición:
public double f(double x) { return Math.Log(x) + 3*x - 10.8074; }
El resto de la implementación es bastante sencilla, y muy similar a otros ejemplos mostrados
anteriormente.

using System;

public class CNewton


{
public double iter;
public double precision;

public CNewton(double pres)


{
iter = 0;
precision = pres;
}

public double f(double x) { return Math.Log(x) + 3*x - 10.8074; }

public double mGetAnswer(double x1)


{
double di, xi1,xi;

xi1 = x1;

do{
xi = xi1;
di = 0.0001 * xi;
xi1 = xi - di * (f(xi) / (f(xi+di)-f(xi)));
iter++;
} while(Math.Abs(xi1-xi) >= precision);

return xi1;
}
}

/***************************************************************************
* Programa que calcula x tal que f(x) = 0, empleando el método de Newton.
* El proceso continúa mientras el valor calculado mantenga una diferencia
* con el valor obtenido en la iteración anterior que sea mayor que una
* precisión dada por el usuario.
***************************************************************************/

public class CMain

IIC 1102 Página: 7


Intro. Prog. Orientada a Objeto – Algoritmos Numéricos Rodrigo Sandoval U.

{
public static void Main()
{
double x,pres;

Console.Write("Ingrese el valor de x: ");


x = Double.Parse(Console.ReadLine());
Console.Write("Ingrese la presicion: ");
pres = Double.Parse(Console.ReadLine());

CNewton nw = new CNewton(pres);

Console.WriteLine("La respuesta es: {0}", nw.mGetAnswer(x));


Console.WriteLine("Para x: {0} con {1} iteraciones", x,nw.iter);
}
}

Ejemplo de ejecución:

Ingrese el valor de X1: 10


Ingrese la precision para el calculo de x: 0.000001

Calculo de x con precision 1.000000e-006:

x = 3.213360870175253400000000000000000000000000000000
f(x) = 0.000000000000000000
Se emplearon 4 iteraciones.

IIC 1102 Página: 8

Anda mungkin juga menyukai