EJERCICIO 1
El método de Newton es un algoritmo muy eficiente para resolver f(x) = 0. Partien-do de un valor inicial x0, el método de Newton obtiene x1, x2, . . . , recursivamente
mediante la fórmula:
xk+1 = xk−
f(xk)
f′(x k)
Escriba un programa en C++ que aplique el método de Newton para resolver: f(x) = x2
− 2 = 0 Puesto que f′(x) = 2x, obtenemos:
xk+1 = xk− f(xk) f′(xk) = xk− x2 k− 2 2xk
El programa debe solicitar que el usuario introduzca por consola el valor inicial (x0) y el número de iteraciones del algoritmo (N).
El programa debe comprobar que el número de iteraciones sea un valor entero mayor que cero. Si no se satisface esta condición, el programa debe terminar. El programa debe escribir en la consola, para k = 0, . . . , N, los valores xk
obteni-dos de aplicar el método de Newton y los correspondientes valores f(xk). Ambos
valores deben mostrarse en formato científico, con 10 dígitos de precisión. A continuación el programa debe terminar.
// Fichero: metodoNewton.cpp #include <iostream> #include <iomanip> #include <cmath> int main() {
// Entrada por consola del valor inicial
std::cout << "Valor inicial: ";
double x_k;
std::cin >> x_k;
// Entrada por consola del número de iteraciones
std::cout << "Numero de iteraciones: ";
int N;
std::cin >> N;
// Comprobar que N es mayor que cero if (N<=0) return 0;
// Método de Newton for (int k=0; k<=N; k++) {
// f(x_k)
double f_k = std::pow(x_k,2) - 2; // Salida por consola
std::cout << k << "\t"<<
std::scientific << std::setprecision(10) << x_k << "\t"<< f_k << "\t"<< std::endl;
// f’(x_k)
double derf_k = 2*x_k; // Iteración del método
x_k = x_k - f_k/derf_k;
}
return 0; }
Consideremos el sistema lineal de ecuaciones Ax= b
donde A es una matriz cuadrada invertible. Supongamos además que la matriz Aes triangular inferior. Esto es:
ai,j = 0 si i < j
En este caso, el sistema lineal Ax = b puede ser resuelto fácilmente. Puede calcularse x1 de la primera ecuación
a1,1x1 = b1
A continuación, puede calcularse x2 de la segunda ecuación
a2,1x1+ a2,2x2 = b2
Y así sucesivamente. En general, una vez se han calculado x1, . . . , xk−1, es posible
emplear la k-ésima ecuación
ak,1x1+ ak,2x2 + · · · + ak,kxk = bk
para calcular xk. Es decir:
xk =
1 ak,k
(bk− ak,1x1− ak,2x2− · · · − ak,k−1xk−1)
Escriba un programa en C++ que dada la matriz A y el vector b, calcule y muestre en la consola el vector de incógnitas x.
El programa tendrá una constante entera N tal que la matriz A sea N × N, y los vectores b y x tengan N componentes. La matriz A y el vector b deben ser constantes del programa. El programa debe realizarse de manera que funcione correctamente para cualquier tamaño de la matriz y los vectores.
// Fichero: sistemaTriangular.cpp #include <iostream>
const int N = 4;
const double b[N] = {1, -2, 0, 4};
const double A[N][N] = { {3, 0, 0, 0},
{1, 1, 0, 0},
{-1, 1, 10, 0},
{1, 1, -1, 4} };
int main() {
std::cout << "Vector de incognitas: "<< std::endl;
double x[N];
for (int i=0; i<N; i++) {
x[i] = b[i];
for (int j=0; j<i; j++)
x[i] = x[i] - A[i][j]*x[j]; x[i] = x[i]/A[i][i];
std::cout << x[i] << std::endl;
}
return 0; }
Se ha realizado una réplica de un experimento factorial completo con 3 facto-res experimentales y dos niveles por factor, que se repfacto-resentan “+” y “−”. Los resultados obtenidos se han almacenado en un fichero de texto. Cada línea del fichero corresponde a un punto experimental. Las tres primeras columnas del fichero indican el punto experimental: la primera columna el nivel del primer factor, la segunda columna el nivel del segundo factor y la tercera columna el nivel del tercer factor. En la cuarta columna se encuentra el correspondiente valor numérico de la respuesta. La estructura del contenido del fichero es la siguiente:
− − − R1 + − − R2 − + − R3 + + − R4 − − + R5 + − + R6 − + + R7 + + + R8
donde R1, . . . , R8 representan los valores numéricos de la respuesta, que son
números reales.
El objetivo del ejercicio es escribir en C++ un programa que lea el contenido del fichero, y calcule y muestre por consola los efectos principales de los tres factores. El efecto principal del factor j se representa ej y es la diferencia entre la respuesta
media cuando el factor j vale “+” y la respuesta media cuando el factor j vale “−”. Es decir: e1 = −R1+ R2− R3+ R4− R5+ R6− R7+ R8 4 e2 = −R1− R2+ R3+ R4− R5− R6+ R7+ R8 4 e3 = −R1− R2− R3 − R4+ R5+ R6+ R7+ R8 4
El programa debe realizar las acciones siguientes:
abrirlo, mostrar un mensaje de error y terminar.
2. Ir leyendo el fichero de texto, comprobando que los puntos experimentales están en el orden correcto. Si el orden no es correcto, mostrar un mensaje de error y terminar.
3. Cerrar el fichero.
4. Calcular los tres efectos principales y mostrarlos en la consola. 5. Terminar.
Así, por ejemplo, si el contenido del fichero datos.txt es − − − 2.5 + − − 1.3 − + − 2.1 + + − 1.5 − − + −2 + − + 1.5 − + + −1.5 + + + 1.3
El programa debería mostrar en la consola: e1 : 1.125
e2 : 0.025 e3 : -2.025
// Fichero: experimento.cpp #include<iostream> #include<fstream> #include<string>
// Nombre del fichero que contiene los datos
const std::string nombreFich = "datos.txt"; int main()
{
std::ifstream fich_in(nombreFich.c_str(), std::ios::in);
if (!fich_in) {
std::cout << "ERROR: No es posible abrir el fichero "<< nombreFich << std::endl;
return 1; }
// Array que almacena las respuestas double R[8];
// Lectura del fichero for (int i=0; i<8; i++) {
char nivel_factor1, nivel_factor2, nivel_factor3; // Lee las tres primeras columnas
fich_in >> nivel_factor1; fich_in >> nivel_factor2; fich_in >> nivel_factor3;
// Comprueba que los puntos experimentales están en el orden correcto int num = 0;
if (nivel_factor1 == ’+’) num += 1; if (nivel_factor2 == ’+’) num += 2; if (nivel_factor3 == ’+’) num += 4; if (num != i) {
std::cout << "Error en linea "<< i+1 <<
": punto experimental en orden incorrecto"<< std::endl;
return 0; }
// Lee la cuarta columna
fich_in >> R[i];
}
// Cierre del fichero
fich_in.close();
// Mostrar los efectos principales
std::cout << "e1 : "<<(-R[0]+R[1]-R[2]+R[3]-R[4]+R[5]-R[6]+R[7])/4 << "\n"<< "e2 : "<<(-R[0]-R[1]+R[2]+R[3]-R[4]-R[5]+R[6]+R[7])/4 << "\n"<< "e3 : "<<(-R[0]-R[1]-R[2]-R[3]+R[4]+R[5]+R[6]+R[7])/4 << std::endl; return 0; }
Código 1.3: Solución al Ejercicio 3.
Escriba en C++ un programa que realice y muestre en la consola la suma de dos números enteros positivos arbitrariamente grandes introducidos por el usuario a través de la consola. El programa debe realizar las acciones siguientes:
1. Solicitar al usuario que introduzca por consola la expresión a evaluar. 2. Almacenar la expresión introducida por el usuario en una variable de tipo
std::string.
3. Comprobar que la expresión introducida por el usuario tiene el formato correcto. Si no lo tiene, mostrar un mensaje de error y terminar. El formato correcto de la expresión es el siguiente:
– Primeramente, uno o más dígitos enteros (0, 1, ..., 9). – A continuación, el símbolo ’+’.
– Finalmente, uno o más dígitos enteros (0, 1, ..., 9).
La expresión no debe contener espacios en blanco. Por ejemplo, la siguiente es una expresión válida:
283746357262816181643862826+362528016129919283473635627262 4. Calcular la suma de los dos números enteros, almacenando el resultado en
una variable de tipo std::string.
Obsérvese que en general los sumandos y el resultado pueden ser mayo-res que el máximo valor repmayo-resentable por los tipos de datos enteros de C++. Por ese motivo, debe programarse un algoritmo que calcule la suma. El algoritmo puede ser cualquiera, siempre que proporcione el resultado correcto. Una posibilidad es emplear el algoritmo que comúnmente se usa al realizar una suma con “papel y lápiz”.
5. Mostrar el resultado de la suma en la consola. 6. Terminar.
// Fichero: sumaEnterosLargos.cpp #include <iostream>
#include <string> int main()
{
// Entrada por consola de la expresión
std::cout << "Introduzca la expresion: "<< std::endl; std::string expresion;
std::cin >> expresion;
// Índice del string en que se encuentra el símbolo + int indMas = expresion.find("+");
if (indMas==-1) {
std::cout << "Error: Falta el simbolo + en la expresion" <<std::endl;
return 0; }
if (indMas==0) {
std::cout << "Error: Falta el primer sumando" <<std::endl;
return 0; }
if (indMas==expresion.length()-1) {
std::cout << "Error: Falta el segundo sumando" <<std::endl;
return 0; }
// Extraer los sumandos
std::string sumando1, sumando2; sumando1.assign(expresion,0,indMas);
sumando2.assign(expresion,indMas+1,expresion.length()-indMas-1);
// Comprobar el formato del primer sumando for (int i=0; i<sumando1.length(); i++) {
if (sumando1[i]<’0’||sumando1[i]>’9’) {
std::cout <<
"Error: El primer sumando no es entero" <<std::endl;
return 0; }
}
// Comprobar el formato del segundo sumando for (int i=0; i<sumando2.length(); i++) {
if (sumando2[i]<’0’||sumando2[i]>’9’) {
std::cout <<
"Error: El segundo sumando no es entero" <<std::endl;
return 0; }
}
Código 1.4: Solución al Ejercicio 4 (primera parte).
// Rellenar con ceros para que ambos sumandos tengan la misma longitud if (sumando1.length() < sumando2.length()) { std::string ceros(sumando2.length()-sumando1.length(),’0’); sumando1.insert(0,ceros); } if (sumando1.length() > sumando2.length()) { std::string ceros(sumando1.length()-sumando2.length(),’0’); sumando2.insert(0,ceros); } // Realiza la suma int acarreo = 0; std::string resultado(sumando1.length(),’0’);
for (int i=sumando1.length()-1; i>=0; i--) { int digito1 = sumando1[i] - ’0’; int digito2 = sumando2[i] - ’0’;
int suma = digito1 + digito2 + acarreo;
resultado[i] = ’0’+ suma %10; acarreo = (int)(suma/10); } if (acarreo>0) { char c = ’0’+ acarreo; std::string cs(1,c); resultado.insert(0,cs); }
// Muestra los sumandos y el resultado en la consola
std::cout << "= "<< resultado << std::endl;
return 0; }