[C++] generowanie sygnału

qwerz
Użytkownik
Użytkownik
Posty: 18
Rejestracja: 16 sty 2016, o 19:20
Płeć: Kobieta
Lokalizacja: Polska
Podziękował: 11 razy

[C++] generowanie sygnału

Post autor: qwerz »

Dzień dobry. Muszę napisać program w C++, który powinien wygenerować sygnał opisany przez taką zależność:

\(\displaystyle{ t=0,...,1 s}\)
\(\displaystyle{ f _{s}=10kHz}\)
\(\displaystyle{ g\left( t\right) = \frac{2}{ \pi } \sum_{p=1}^{30} \frac{ \left( -1^{p} \right) }{p}\left[ \cos \left( \frac{p \cdot \pi \cdot 0.05f _{s}}{0.15f _{s}} \right)-1 \right]\sin \left( \frac{p \cdot \pi \cdot t}{0.15f _{s}} \right)}\)

Domyślam się, że skoro czas trwania ma wynosić 1 sekundę, a częstotliwość wynosi 10000 Hz, to trzeba tu zrobić pętlę for od 1 do 10000, ale nie za bardzo wiem, jak podejść do tej sumy od \(\displaystyle{ p=1}\) do \(\displaystyle{ p=30}\), tzn. jaka jest jej zależność od kolejnych iteracji. Czy mogłabym prosić o jakieś wskazówki?
Ostatnio zmieniony 28 paź 2017, o 17:02 przez Afish, łącznie zmieniany 1 raz.
Powód: Poprawa wiadomości.
Awatar użytkownika
Igor V
Użytkownik
Użytkownik
Posty: 1605
Rejestracja: 16 lut 2011, o 16:48
Płeć: Mężczyzna
Lokalizacja: Polska
Podziękował: 18 razy
Pomógł: 604 razy

Re: [C++] generowanie sygnału

Post autor: Igor V »

Nie no, \(\displaystyle{ f_s}\) to pewnie częstotliwość próbkowania, więc jest ustalona (zresztą pisze).
Zrób pierwszą pętlę po ilości kwantów czasu \(\displaystyle{ t}\), które musisz sobie jakoś wyznaczyć z tego przedziału \(\displaystyle{ [0, 1]}\) (np: liniowo). Drugą (wewnętrzną) zrób po \(\displaystyle{ p \in \{1,2\dots 30\}}\) gdzie sumujesz wartości.-- 28 paź 2017, o 17:22 --EDIT: Tak, liniowo - bo wyznaczysz sobie te punkty z \(\displaystyle{ f_s}\) po prostu. Czyli ta pierwsza pętla zgadza się z tym co napisałaś.
qwerz
Użytkownik
Użytkownik
Posty: 18
Rejestracja: 16 sty 2016, o 19:20
Płeć: Kobieta
Lokalizacja: Polska
Podziękował: 11 razy

Re: [C++] generowanie sygnału

Post autor: qwerz »

Napisałam coś takiego:

Kod: Zaznacz cały

    double czas[10000];
    double g[10000];
    double pi = M_PI;
    double t, dzialanie, suma = 0.0;

    for (int i=0; i<10000; ++i)
    {
        t=(i+1.0)/10000.0;
        czas[i]=t;
        for (int j=0; j<30; ++j)
        {
            dzialanie = (std::pow((-1.0),j) / j) * (cos((j*pi*0.05*10000.0) / (0.15*10000.0))-1.0) * sin((j*pi*t)/(0.15*10000.0));
            if((dzialanie==dzialanie)==false)
                dzialanie=0;
            suma=suma+dzialanie;
        }
        g[i]=(2/pi)*suma;
        std::cout << czas[i] << "	"<< g[i] << std::endl;
    }
Chyba tak to powinno być zrobione?
Niestety czasami dzialanie dawało -nan, więc wtedy ustawiam jego wartość na 0. Ogólnie po wypisaniu czas[i] i g[i] do pliku i złożeniu z tego wykresu \(\displaystyle{ g\left( t\right)}\) wychodzi coś takiego:

Ostatnio zmieniony 29 paź 2017, o 10:09 przez qwerz, łącznie zmieniany 1 raz.
Awatar użytkownika
Igor V
Użytkownik
Użytkownik
Posty: 1605
Rejestracja: 16 lut 2011, o 16:48
Płeć: Mężczyzna
Lokalizacja: Polska
Podziękował: 18 razy
Pomógł: 604 razy

Re: [C++] generowanie sygnału

Post autor: Igor V »

1. Nie powinnaś porównywać typów zmiennoprzecinkowych przez \(\displaystyle{ ==}\) ze względu na zaokrąglenia. Trzeba dawać zawsze jakiś margines.
2. Masz wartości niezdefiniowane zapewne dlatego że dla \(\displaystyle{ j = 0}\) jest dzielenie przez \(\displaystyle{ 0}\).
3. Nie jestem przekonany do końca na temat metody generacji czasu.
4. Uwaga praktyczna - wszelkie parametry najwygodniej zapisywać w postaci nazw i tak ich używać. Jak zmieni Ci się jakiś to nie musisz potem grzebać po całym programie + pstwo pomyłki przy zamianie jest mniejsze.

Kod: Zaznacz cały

#include <iostream>
#include <math.h>

using namespace std;

const double F_S = 10e3;
const double LEFT_TIME_POINT = 0;
const double RIGHT_TIME_POINT = 1;
const int MAX_SUM_INDEX = 30;
const double PI = M_PI;

double fancy_signal(int max_sum_index, double pi, double f_s, double time_point)
{
    double output = 0;

    for(int i = 1; i <= max_sum_index; i++)
    {
        output += (pow(-1, i)/i)*(cos((i*pi*0.05)/0.15) - 1)*sin((i*pi*time_point)/(0.15*f_s));
    }

    output = (2/pi)*output;
    return output;
}

int main()
{
    double time = RIGHT_TIME_POINT - LEFT_TIME_POINT;
    int number_of_points = (int)F_S*time;
    double step = time/(number_of_points - 1);
    double g[number_of_points];
    double time_vector[number_of_points];

    for(int i = 0; i < number_of_points; i++)
    {
        time_vector[i] = LEFT_TIME_POINT + i*step;
        g[i] = fancy_signal(MAX_SUM_INDEX, PI, F_S, time_vector[i]);
    }

    return 0;
}
Ogólnie wyszło mi coś podobnego (w sensie kształtu), tyle że inne wartości.

Kod: Zaznacz cały

http://wstaw.org/h/52f30151129/
ODPOWIEDZ