Página 1 de 1

Como resolver esta secuencia geometrica?C++

MensajePublicado:03 Oct 2017, 04:18
por Destr0yer
Buenas necesito de vuestra ayuda para resolver este ejercicio:
Imagen
esto es lo que he avanzado, sin embargo , no se en que parte podría colocar la variable 'y' ; gracias
Imagen

Re: Como resolver esta secuencia geometrica?C++

MensajePublicado:11 Oct 2017, 00:06
por Slek
Buenas,
con este ejemplo creo que se pueden ilustrar bastante bien algunos conceptos iteresantes de programación.

Una primera implementación podría ser:
#include <iostream>
#include <string>

#define N_MAX 30
#define EPSILON 0.00001

int main ()
{
    std::string s;
    int n;
    double a, x, y;

    do
    {
        std::cout << "Ingrese el número de términos (N): ";
        std::getline(std::cin, s);

        n = std::stoi(s);
    } while ((n <= 0) || (n > N_MAX));

    do
    {
        std::cout << "Ingrese el valor de a: ";
        std::getline(std::cin, s);

        a = std::stod(s);
    } while (std::abs(a) < EPSILON);

    std::cout << "Ingrese el valor de x: ";
    std::getline(std::cin, s);

    x = std::stod(s);

    std::cout << "Ingrese el valor de y: ";
    std::getline(std::cin, s);

    y = std::stod(s);

    double termino, suma = 0., signo = -1., cociente = 3., denominador = 1.;
    for (int k = 1; k <= n; k++)
    {
        termino = ((k & 1) ? x:y)*signo*cociente/denominador;
        suma += termino;
        denominador *= 2*a;
        signo *= -1.;
        cociente += 3.;
    }

    std::cout << std::endl << "La sumatoria es: " << suma << std::endl;

    return 0;
}
utilizando el operador ternario ?:

Sería sintácticamente equivalente a:
        if (k & 1)[code][/code]
            termino = x;
        else
            termino = y;
        termino *= signo*cociente/denominador;
//        termino = ((k & 1) ? x:y)*signo*cociente/denominador;

Para comprobar si un número es par o impar, basta con evaluar el último bit (eso es precisamente lo que hace k & 1).

En estas ocasiones podría ser interesante aplicar técnicas de desenrollado de bucles. Por ejemplo, evaluando los términos de dos en dos:
#include <cmath>

    double suma = 0.;
    for (int k = 1; k <= n/2; k++)
    {
        suma -= 3*x*(2*k - 1)/std::pow(2*a, 2*(k-1));
        suma += 3*y*2*k/std::pow(2*a, 2*k-1);
    }

    if (n & 1)
        suma -= (3*x*n)/std::pow(2*a, n-1);

Además podemos sacar la condición fuera del bucle (solo se evalua una vez). De esta forma reducimos aún más el número de saltos ejecutados.

Por último, si la eficiencia es un problema, podemos eliminar los bucles for por completo, evaluando es su lugar las funciones de suma parcial asociadas:
double suma = -3*x*evalSumX(4*a*a, n/2 + (n & 1)) + 3*y*evalSumY(2*a, n/2);
donde:
#include <cassert>
#include <cmath>

double evalSumX(double a, int n)
{
    assert(n > 0);

    if (std::abs(a - 1.) >= EPSILON)
    {
        double an = std::pow(a, n);
        return a*(an*a+an-a*(2*n+1)+2*n-1)/(an*(a-1)*(a-1));
    }
    else
        return n*n;
}

double evalSumY(double a, int n)
{
    assert(n > 0);

    double a2 = a*a;
    if (std::abs(a2 - 1.) >= EPSILON)
    {
        double a2n = std::pow(a2, n);
        return 2*a*(a2*a2n-a2*(n+1)+n)/(a2n*(a2-1)*(a2-1));
    }
    else
        return n*(n+1);
}
con complejidad constante O(1), en lugar de lineal respecto al número de términos (O(n))

Cualquier duda, preguntad.

Un saludo!