LENGUAJES DE PROGRAMACIÓN Solución al Trabajo

Anuncio
LENGUAJES DE PROGRAMACIÓN
Solución al Trabajo Práctico - Septiembre de 2016
EJERCICIO 1
El método del punto fijo es un método para resolver una ecuación de la forma
f (x) = x
El método consiste en elegir un valor inicial x0 y realizar la iteración
xi+1 = f (xi )
hasta que la diferencia |xi+1 − xi | sea inferior a una determinada tolerancia.
Escriba un programa en C++ que aplique el método del punto fijo a la resolución
de la ecuación


σ · 1.99 − 0.41 ·
x
w
+ 18.70 ·
K
x 2
w
2
− 38.48 ·
x 3
w
+ 53.85 ·
x 4
w
 = x
donde w = 2.5, σ = 24.89 y K = 52. Escoja como valor inicial para la iteración
x0 = 0.25 y un valor de la tolerancia igual a 1E − 3.
El programa debe ir escribiendo en la consola los valores xi y |f (xi ) − xi | para
i = 0, 1, . . . , en formato fijo y con 6 dígitos decimales.
Si el número de iteraciones alcanza un cierto valor maxIter = 50, el programa
debe finalizar indicando que el método ha excedido el número máximo de iteraciones.
LENGUAJES DE PROGRAMACIÓN
Incluya en la memoria del trabajo dos capturas de pantalla de la salida por consola. En una de las capturas de pantalla deben mostrarse los resultados de las
primeras iteraciones. En la otra captura de pantalla deben mostrarse los resultados de las últimas iteraciones.
A continuación, modifique el valor del número máximo de iteraciones a maxIter =
200 y ejecute nuevamente el programa. Incluya en la memoria una captura de
pantalla donde se muestre en este caso el resultado obtenido en las últimas iteraciones.
2
Dpto. de Informática y Automática, UNED
SOLUCIÓN AL TRABAJO PRÁCTICO - SEPTIEMBRE DE 2016
Solución al Ejercicio 1
#include <iostream>
#include <cmath>
#include <iomanip>
const double Tolerancia = 1E-3;
const double w = 2.5;
const double sigma = 24.89;
const double K = 52;
const double x0 = 0.25;
const int maxIter = 200;
// 50;
double f(double x) {
double xw = x/w;
const double c[] = {1.99,-0.41,18.70,-38.48,53.85};
double y = c[0];
double powxw = 1;
for (unsigned int i=1; i<=4; i++) {
powxw *= xw;
y += c[i]*powxw;
}
return std::pow( K/(sigma*y), 2.0 );
}
int main() {
// Valores iniciales
int i = 0;
double x = x0;
// x_{i}
bool iterar = true;
// Iteración
while ( iterar && i <= maxIter ) {
double fx = f(x);
// x_{i+1}
double err = std::fabs(x-fx);
std::cout << "i = " << i
<< std::fixed << std::setprecision(6)
<< "\tx = " << x
<< "\tabs(x-f(x)) = " << err
<< std::endl;
iterar = ( err >= Tolerancia );
x = fx;
i++;
}
if ( iterar )
std::cout << "Alcanzado numero maximo de iteraciones"
<< std::endl;
return 0;
}
Código 1.1: Programa solución al Ejercicio 1.
Dpto. de Informática y Automática, UNED
3
LENGUAJES DE PROGRAMACIÓN
EJERCICIO 2
Escriba un programa en C++ que calcule y escriba en la consola el producto de
dos números naturales leídos de un fichero de texto. Cada número está escrito
en una línea diferente del fichero, por lo que éste contiene dos líneas de texto. El
programa debe realizar las acciones siguientes:
1. Solicitar y leer el nombre del fichero. Mediante un mensaje en la consola, solicitar al usuario que introduzca el nombre del fichero de texto donde están
escritos los dos números. Leer el nombre introducido por el usuario.
2. Leer el fichero. Abrir para lectura el fichero de texto. Si se produce error,
terminar. En caso contrario, leer el contenido del fichero.
Dado que los números escritos en el fichero pueden ser lo suficientemente
grandes como para estar fuera del rango de los tipos de datos de los números enteros, el programa almacenará cada uno de los dos números en un
string.
3. Comprobar que cada uno de los dos strings leídos contiene un número natural.
Para ello, debe comprobarse que todos los componentes de los strings son
dígitos. En caso contrario, mostrar un mensaje indicándolo y terminar.
4. Comprobar que los números naturales están dentro de los límites para las variables
de tipo unsigned long int. Si alguno de los números leídos está fuera del
rango de valores de este tipo de dato, mostrar un mensaje indicándolo y
terminar.
5. Conversión de tipo. Almacenar los números naturales escritos en los dos strings
en sendas variables del tipo unsigned long int.
6. Comprobar que el producto de los dos números está dentro de los límites para
las variables de tipo unsigned long int. Si no lo está, mostrar un mensaje
indicándolo y terminar.
7. Mostrar en la consola el resultado de la multiplicación de los dos números.
8. Terminar.
4
Dpto. de Informática y Automática, UNED
SOLUCIÓN AL TRABAJO PRÁCTICO - SEPTIEMBRE DE 2016
Solución al Ejercicio 2
#include <iostream>
#include <string>
#include <fstream>
#include <limits>
#include <sstream>
const unsigned long int MAX = std::numeric_limits<unsigned long int>::max();
int main() {
// Nombre del fichero
std::cout << "Nombre del fichero: ";
std::string nombreFich;
std::cin >> nombreFich;
// Apertura del fichero de comandos para lectura
std::ifstream inFich(nombreFich.c_str(), std::ios::in);
if (!inFich) {
std::cout << "ERROR al abrir fichero "
<< nombreFich << std::endl;
return 1;
}
// Lectura de dos palabras del fichero
std::string palabra1, palabra2;
inFich >> palabra1;
if (inFich.eof()) {
std::cout << "Datos no validos en el fichero" << std::endl;
return 0;
}
inFich >> palabra2;
inFich.close();
// Comprobar que lo leido son numeros naturales
for (unsigned int i=0; i<palabra1.size(); i++)
if (palabra1[i] < '0' || palabra1[i] > '9') {
std::cout << "Dato no valido: " << palabra1 << std::endl;
return 0;
}
for (unsigned int i=0; i<palabra2.size(); i++)
if (palabra2[i] < '0' || palabra2[i] > '9') {
std::cout << "Dato no valido: " << palabra2 << std::endl;
return 0;
}
Código 1.2: Programa solución al Ejercicio 2 (inicio).
Dpto. de Informática y Automática, UNED
5
LENGUAJES DE PROGRAMACIÓN
}
// Comprobación de que los números están dentro de los límites
std::stringstream ss;
ss << MAX;
std::string sMAX = ss.str();
bool palabra1_fueraLimite = sMAX.size() < palabra1.size() ||
(sMAX.size() == palabra1.size() && sMAX < palabra1);
if ( palabra1_fueraLimite ) {
std::cout << "Primer entero fuera de limite" << std::endl;
return 0;
}
bool palabra2_fueraLimite = sMAX.size() < palabra2.size() ||
(sMAX.size() == palabra2.size() && sMAX < palabra2);
if ( palabra2_fueraLimite ) {
std::cout << "Segundo entero fuera de limite" << std::endl;
return 0;
}
// Almacenar los números en variables del tipo unsigned long int
unsigned long int num1 = 0, num2 = 0;
unsigned long int expo = 1;
for (unsigned int i=0; i<palabra1.size(); i++) {
num1 += (palabra1[palabra1.size()-i-1] - '0')*expo;
expo *= 10;
}
expo = 1;
for (unsigned int i=0; i<palabra2.size(); i++) {
num2 += (palabra2[palabra2.size()-i-1] - '0')*expo;
expo *= 10;
}
// Comprobación de que el producto está dentro de límite
if ( num2 > MAX / num1 ) {
std::cout << "El producto esta fuera de limites" << std::endl;
return 0;
}
std::cout << "Resultado: " << num1 * num2 << std::endl;
return 0;
Código 1.3: Programa solución al Ejercicio 2 (final).
6
Dpto. de Informática y Automática, UNED
SOLUCIÓN AL TRABAJO PRÁCTICO - SEPTIEMBRE DE 2016
EJERCICIO 3
El objetivo es nuevamente calcular el producto de dos números naturales escritos
en un fichero de texto, pero en esta ocasión la estrategia a seguir es diferente ya
que se pretende poder calcular el producto de números naturales arbitrariamente
largos. El programa debe realizar las acciones siguientes (obsérvese que las tres
primeras coinciden con las del ejercicio anterior):
1. Solicitar y leer el nombre del fichero. Mediante un mensaje en la consola, solicitar al usuario que introduzca el nombre del fichero de texto donde están
escritos los dos números. Leer el nombre introducido por el usuario.
2. Leer el fichero. Abrir para lectura el fichero de texto. Si se produce error,
terminar. En caso contrario, leer el contenido del fichero almacenando cada
uno de los dos números en un string.
3. Comprobar que cada uno de los dos strings leídos contiene un número natural.
Para ello, debe comprobarse que todos los componentes de los strings son
dígitos. En caso contrario, mostrar un mensaje indicándolo y terminar.
4. Conversión de tipo. Almacenar los números naturales escritos en los dos strings
en sendos vectores de int, de manera que cada dígito del número quede
almacenado en un componente del vector.
5. Multiplicación de los dos números naturales. La multiplicación debe realizarse
aplicando el procedimiento clásico empleado al operar con “lápiz y papel”.
El algoritmo de la multiplicación debe aplicarse operando los dos vectores
de dígitos, obteniéndose como resultado otro vector de dígitos.
El procedimiento clásico de multiplicación con lápiz y papel consiste en
ir multiplicando por el primer factor los dígitos del segundo factor, comenzando por el menos significativo. Los resultados obtenidos se suman
desplazados cada uno una posición hacia la izquierda respecto al anterior.
A continuación se muestra un ejemplo.
×
1
15
115
132
385474365678
3
927371828393
418974627150
642309703628
988656159172
76
45
80
4
20
6. Mostrar el resultado en la consola y terminar.
Dpto. de Informática y Automática, UNED
7
LENGUAJES DE PROGRAMACIÓN
Solución al Ejercicio 3
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
int main() {
// Nombre del fichero
std::cout << "Nombre del fichero: ";
std::string nombreFich;
std::cin >> nombreFich;
// Apertura del fichero de comandos para lectura
std::ifstream inFich(nombreFich.c_str(), std::ios::in);
if (!inFich) {
std::cout << "ERROR al abrir fichero "
<< nombreFich << std::endl;
return 1;
}
// Lectura de dos palabras del fichero
std::string palabra1, palabra2;
inFich >> palabra1;
if (inFich.eof()) {
std::cout << "Datos no validos en el fichero" << std::endl;
return 0;
}
inFich >> palabra2;
inFich.close();
// Comprobar que lo leido son numeros naturales
for (unsigned int i=0; i<palabra1.size(); i++)
if (palabra1[i] < '0' || palabra1[i] > '9') {
std::cout << "Dato no valido: " << palabra1 << std::endl;
return 0;
}
for (unsigned int i=0; i<palabra2.size(); i++)
if (palabra2[i] < '0' || palabra2[i] > '9') {
std::cout << "Dato no valido: " << palabra2 << std::endl;
return 0;
}
// Almacenar los números en vectores
// índice 0 del vector = digito menos significativo del número
std::vector<int> num1, num2;
for (int i=palabra1.size()-1; i>=0; i--)
num1.push_back(palabra1[i] - '0');
for (int i=palabra2.size()-1; i>=0; i--)
num2.push_back(palabra2[i] - '0');
Código 1.4: Programa solución al Ejercicio 3 (inicio).
8
Dpto. de Informática y Automática, UNED
SOLUCIÓN AL TRABAJO PRÁCTICO - SEPTIEMBRE DE 2016
}
// Producto
std::vector<int> resultado;
for (unsigned int j=0; j<num2.size(); j++) {
std::vector<int> resultadoP; // num2[j] * num1
int acarreoP = 0;
for (unsigned int i=0; i<num1.size(); i++) {
int prod = num1[i] * num2[j] + acarreoP;
resultadoP.push_back( prod % 10 );
acarreoP = prod / 10;
}
if ( acarreoP != 0 )
resultadoP.push_back( acarreoP);
// Desplaza y suma
int acarreoS = 0;
for (unsigned int i=0; i<resultadoP.size(); i++) {
if ( resultado.size() > j + i ) {
int suma = resultado[j+i] + resultadoP[i] + acarreoS;
resultado[j+i] = suma % 10;
acarreoS = suma / 10;
} else {
int suma = resultadoP[i] + acarreoS;
resultado.push_back(suma %10);
acarreoS = suma / 10;
}
}
if (acarreoS != 0)
resultado.push_back(acarreoS);
}
// Mostrar resultado en la consola
std::cout << "FACTORES:" << std::endl;
for (int i=num1.size()-1; i>=0; i--)
std::cout << num1[i];
std:: cout << std::endl;
for (int i=num2.size()-1; i>=0; i--)
std::cout << num2[i];
std:: cout << "\nPRODUCTO:\n";
bool noCero = false;
for (int i=resultado.size()-1; i>=0; i--) {
if (noCero || resultado[i] != 0) { // Elimina ceros a la izquierda
std::cout << resultado[i];
noCero=true;
}
}
if (!noCero)
std::cout << "0";
std::cout << std::endl;
return 0;
Código 1.5: Programa solución al Ejercicio 3 (final).
Dpto. de Informática y Automática, UNED
9
LENGUAJES DE PROGRAMACIÓN
EJERCICIO 4
El algoritmo de Karatsuba permite realizar la multiplicación de dos números
enteros grandes por medio de la multiplicación, suma y resta de números enteros
más pequeños. Un caso particular del algoritmo de Karatsuba permite calcular el
producto de dos números enteros x e y, expresados de la forma:
x = x1 · 103 + x0
y = y1 · 103 + y0
de la manera siguiente:
x · y = z2 · 106 + z1 · 103 + z0
donde z2 , z1 y z0 se calculan de la forma siguiente:
z2 = x1 · y1
z0 = x0 · y0
z1 = (x1 + x0 ) · (y1 + y0 ) − z2 − z0
En la Figura 1.1 se muestra un ejemplo de aplicación del algoritmo. Obsérvese
que las multiplicaciones necesarias para calcular z2 , z1 y z0 , pueden ser calculadas
aplicando este mismo algoritmo de forma recursiva si al menos uno de los dos
factores es mayor que 999. Si los dos factores son menores que 999, el producto se
realiza de la manera ordinaria.
Escribir un programa en C++ que realice las acciones siguientes:
1. Solicitar que el usuario introduzca por consola dos números enteros.
2. Comprobar que el producto de los dos números está dentro de los límites
para las variables del tipo long long int. Si no lo está, mostrar un mensaje
indicándolo y terminar.
3. Calcular el producto de los dos números aplicando el algoritmo de Karatsuba.
4. Mostrar el resultado en la consola.
5. Terminar.
10
Dpto. de Informática y Automática, UNED
SOLUCIÓN AL TRABAJO PRÁCTICO - SEPTIEMBRE DE 2016
Figura 1.1: Ejemplo de aplicación del algoritmo de Karatsuba.
Dpto. de Informática y Automática, UNED
11
LENGUAJES DE PROGRAMACIÓN
Solución al Ejercicio 4
#include <iostream>
#include <limits>
#include <cmath>
const long long int MAX = std::numeric_limits<long long int>::max();
long long int Karatsuba(long long int x, long long int y) {
long long int x1 = x/1000;
long long int y1 = y/1000;
if ( x1 == 0 && y1 == 0 )
return x*y;
long long int x0 = x % 1000;
long long int y0 = y % 1000;
long long int z2 = Karatsuba(x1,y1);
long long int z0 = Karatsuba(x0,y0);
long long int z1 = Karatsuba(x1+x0,y1+y0) - z2 - z0;
return z2*1000000 + z1*1000 + z0;
}
int main() {
// Solicitar que el usuario introduzca los factores
std::cout << "Introduzca los factores: ";
long long int x, y;
std::cin >> x >> y;
// Comprobación de que el producto está dentro de los límites
if ( std::abs(MAX/x) < y ) {
std::cout << "Producto fuera de limite" << std::endl;
return 0;
}
// Aplicación del algoritmo de Karatsuba
std::cout << "Producto: "
<< Karatsuba(x,y) << std::endl;
return 0;
}
Código 1.6: Programa solución al Ejercicio 4.
12
Dpto. de Informática y Automática, UNED
Descargar