2016-03-26 9 views
7

मैं असतत फूरियर करने के लिए कोशिश कर रहा हूँ सीअसतत फूरियर गलत परिणाम

शुरू में सिर्फ जानवर बल विधि में बदल देती देने को बदलने। सबसे पहले मैंने प्रोग्राम डेटा फ़ाइल (आयामों) को खोल दिया था और डेटा को सरणी में रखा था (केवल एक, क्योंकि मैं खुद को वास्तविक मूल्यवान इनपुट तक सीमित कर रहा हूं)।

लेकिन परिवर्तन गलत लग रहा था, इसलिए इसके बजाय मैंने एक सरल तरंग उत्पन्न करने की जांच की और जांच की कि यह ठीक से बदलता है या नहीं।

यहाँ मेरी कोड, घंटियां और सीटियां छीन है: पूरा करता है, लेकिन बजाय एक शक्ति (आवृत्ति) भूखंड पर कई तेज चोटियों की,

#include <math.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define M_PI 3.14159265358979323846 

//the test wavefunction 
double theoretical(double t) 
{ 
    double a = sin(M_PI * t) + 2 * sin(2 * M_PI * t) + 4 * sin(4 * M_PI * t); 
    return a; 
} 
//------------------------------------------------------------------------- 
void dftreal(double inreal[], double outreal[], double outimag[], int linecount) 
{ 
    int n, k; 
    for (k = 0; k < linecount; k++) 
    { 
     double sumreal = 0; 
     double sumimag = 0; 

     for (n = 0; n < linecount; n++) 
     { 
      double angle = 2 * M_PI * n * (k/(double) linecount); 
      sumreal += inreal[n] * cos(angle); 
      sumimag += inreal[n] * sin(angle); 
     } 
     outreal[k] = sumreal; 
     outimag[k] = sumimag; 
    } 
} 
//========================================================================= 
int main(void) 
{ 
    int linecount = 44100; 
    //creates all necessary arrays 
    double inreal[linecount], outreal[linecount], outimag[linecount], p[linecount]; 

    FILE *fout = fopen("Output.txt", "w"); 

    for (int i = 0 ; i < linecount ; ++i) 
    { 
     inreal[i] = theoretical(i/(double) linecount); 
    } 

    //actually computes the transform 
    dftreal(inreal, outreal, outimag, linecount); 

    for (int i = 0 ; i < linecount ; ++i) 
    { 
      p[i] = 2*(outreal[i] * outreal[i] + outimag[i] * outimag[i]); 
      fprintf(fout, "%f %f \n", (i/(double) linecount), p[i]); 
    } 
    fclose(fout); 
    printf("\nEnd of program"); 
    getchar(); 
    return 0; 
} 

कार्यक्रम को संकलित करता है, मैं इस मिल: I get this.

एक आवृत्ति या विभिन्न आवृत्तियों सटीक समान उलटा-बाथटब-वक्र देते हैं।

मैं एफ टी के बारे में कई स्रोतों की जाँच की और मैं अभी भी नहीं जानता कि क्या गलत हो रहा है, वहाँ समारोह के साथ किसी भी स्पष्ट त्रुटियों होने लगते नहीं है:

dftreal 

ही। मैं इस मुद्दे के कारण क्या हो सकता है इस बारे में मदद मांगना चाहता हूं। मैं विंडोज 7 पर मिनीजीडब्ल्यू कंपाइलर का उपयोग कर रहा हूं। धन्यवाद!

+0

डीएफटी उच्च दशमलव परिशुद्धता की आवश्यकता है। क्या आपने अपने fprintf कथन को बदलने की कोशिश की है ताकि वे अधिक दशमलव शामिल कर सकें? % .10f या अधिक की तरह ... –

उत्तर

2

अच्छी खबर अपने dftreal कार्यान्वयन के साथ कुछ भी गलत नहीं है:

वैसे भी, यहाँ कोड [नि: शुल्क शैली सफाई कृपया क्षमा] है।

समस्या, अगर कोई इसे कॉल कर सकता है, तो यह है कि परीक्षण तरंग का उपयोग आप आवृत्ति घटकों में शामिल करते हैं जो आपके नमूना दर linecount के सापेक्ष बहुत कम आवृत्तियों के होते हैं। इसके अनुरूप, डीएफटी से पता चलता है कि ऊर्जा पहले कुछ डिब्बे में केंद्रित है, कुछ तरंग रिसाव उच्च डिब्बे में है क्योंकि तरंग आवृत्ति घटकों नमूना दर के सटीक गुणक नहीं हैं।

आप उदाहरण के लिए के साथ नमूना आवृत्ति को आवृत्ति रिश्तेदार बनाकर परीक्षण तरंग आवृत्तियों को बढ़ाते हैं:

//the test wavefunction 
double theoretical(double t) 
{ 
    double f = 0.1*44100; 
    double a = sin(2 * M_PI * f * t) + 2 * sin(4 * M_PI * f * t) + 4 * sin(8 * M_PI * f * t); 
    return a; 
} 

आप इस तरह के रूप में एक भूखंड मिलना चाहिए: dftreal output with higher frequency test waveform

+0

आप निश्चित रूप से सही हैं। मुझे नहीं पता कि मैं कैसे गणित को इतनी बुरी तरह उलझाने में कामयाब रहा, कार्यक्रम अब इरादे से काम करता है। आपका बहुत बहुत धन्यवाद! – Ravenchant

1

चेतावनी: मैं इसे याद है, क्योंकि जैसा कि मैंने थोड़ा इस

पर जंग लगी हूँ/वास्तविक हिस्सा आवृत्ति स्पेक्ट्रम और पाप/imag हिस्सा बिजली स्पेक्ट्रम पैदावार अर्जित करता है। तो, जो मुझे लगता है कि आप प्रिंट करना चाहते हैं वह आवृत्ति स्पेक्ट्रम है (जो कि outreal[i] है) जो आपने किया था (यानी outreal और outimag गलत है)। आप दोनों अलग-अलग रंगों में साजिश कर सकते हैं लेकिन मैं बस शुरू करूंगा।

इसके अलावा, मैं सरल डेटा इनपुट के साथ शुरू करूंगा।

मैंने theoretical को एक एकल कोसाइन लहर [साथ ही साथ आपका मूल] करने के लिए बदल दिया। यह अनुमान लगाया जा सकता है और आपको एक ही स्पाइक मिलना चाहिए, जो आपको लगता है, इसलिए मुझे लगता है कि dftreal सही है।

मैंने कुछ कमांड लाइन विकल्प भी जोड़े ताकि आप प्रयोग कर सकें।

मैंने यह भी पाया कि i/linecount को विभाजित करने से कभी-कभी छंटनी हो जाती है, इसलिए मैंने इसे FRAG मैक्रो बनाया/इसे सही करने के लिए बनाया। इस के बिना, cos(2 * pi * t) के इनपुट के लिए कील outreal[1]

इसके अलावा के बजाय outreal[0] में समाप्त हो गया (डीसी हिस्सा?), परीक्षण प्रयोजनों के लिए, आप अब तक कम नमूने (जैसे 1000) के साथ प्राप्त कर सकते हैं। यह चीजों को देखने में बेहतर होने के लिए क्षैतिज रूप से अपनी साजिश फैलाने में भी मदद कर सकता है।

#include <math.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 

//#define M_PI 3.14159265358979323846 
#define M_2PI (M_PI * 2.0) 

int opt_A;        // algorithm to use 
int linecount;       // number of samples 
int opt_a;        // use absolute value on output 
int opt_s;        // use squared value on output 
int opt_i;        // use integer output index 
int opt_j;        // output imaginary part 
int opt_c;        // .csv compatibility 

time_t todlast; 

// the first was your original and would truncate 
#if 0 
#define FRAG(_i) ((_i)/linecount) 
#else 
#define FRAG(_i) ((double) (_i)/linecount) 
#endif 

void 
pgr(int k,int n,int count) 
{ 
    time_t todnow = time(NULL); 

    if ((todnow - todlast) >= 1) { 
     todlast = todnow; 
     printf("\r%d %d ",count,k); 
     fflush(stdout); 
    } 
} 

// the test wavefunction 
double 
theoretical(double t) 
{ 
    double a; 

    switch (opt_A) { 
    case 0: 
     a = 0.0; 
     a += sin(M_PI * t); 
     a += 2.0 * sin(2.0 * M_PI * t); 
     a += 4.0 * sin(4.0 * M_PI * t); 
     break; 
    default: 
     a = cos(M_2PI * t * opt_A); 
     break; 
    } 

    return a; 
} 

//------------------------------------------------------------------------- 
void 
dftreal(double inreal[], double outreal[], double outimag[], int linecount) 
{ 
    int n; 
    int k; 

    for (k = 0; k < linecount; k++) { 
     double sumreal = 0; 
     double sumimag = 0; 
     double omega_k = (M_2PI * k)/(double) linecount; 

     for (n = 0; n < linecount; n++) { 
      // omega k: 
#if 0 
      double angle = M_2PI * n * FRAG(k); 
#else 
      double angle = omega_k * n; 
#endif 

      sumreal += inreal[n] * cos(angle); 
      sumimag += inreal[n] * sin(angle); 

      pgr(k,n,linecount); 
     } 

     outreal[k] = sumreal; 
     outimag[k] = sumimag; 
    } 
} 

//========================================================================= 
int 
main(int argc,char **argv) 
{ 
    char *cp; 

    --argc; 
    ++argv; 

    for (; argc > 0; --argc, ++argv) { 
     cp = *argv; 
     if (*cp != '-') 
      break; 

     switch (cp[1]) { 
     case 'a': // absolute value 
      opt_a = ! opt_a; 
      break; 
     case 's': // square the output value 
      opt_s = ! opt_s; 
      break; 
     case 'c': // .csv output 
      opt_c = ! opt_c; 
      break; 
     case 'i': // integer output 
      opt_i = ! opt_i; 
      break; 
     case 'j': // imaginary output 
      opt_j = ! opt_j; 
      break; 
     case 'A': 
      opt_A = atoi(cp + 2); 
      break; 
     case 'N': 
      linecount = atoi(cp + 2); 
      break; 
     } 
    } 

    if (linecount <= 0) 
     linecount = 44100/2; 

    // creates all necessary arrays 
    double inreal[linecount]; 
    double outreal[linecount]; 
    double outimag[linecount]; 
#if 0 
    double p[linecount]; 
#endif 

    FILE *fout = fopen("Output.txt", "w"); 

    for (int i = 0; i < linecount; ++i) 
     inreal[i] = theoretical(FRAG(i)); 

    todlast = time(NULL); 

    // actually computes the transform 
    dftreal(inreal, outreal, outimag, linecount); 

    for (int i = 0; i < linecount; ++i) { 
#if 0 
     p[i] = 2 * (outreal[i] * outreal[i] + outimag[i] * outimag[i]); 
     fprintf(fout, "%f %f\n", (i/(double) linecount), p[i]); 
#endif 

#if 0 
     fprintf(fout, "%f %f %f\n", (i/(double) linecount), 
      outreal[i] * outreal[i], 
      outimag[i] * outimag[i]); 
#endif 

#if 0 
     fprintf(fout, "%f %f\n", 
      (i/(double) linecount),outreal[i] * outreal[i]); 
#endif 

     if (opt_a) { 
      outreal[i] = fabs(outreal[i]); 
      outimag[i] = fabs(outimag[i]); 
     } 

     if (opt_s) { 
      outreal[i] *= outreal[i]; 
      outimag[i] *= outimag[i]; 
     } 

     if (! opt_c) { 
      if (opt_i) 
       fprintf(fout, "%d ",i); 
      else 
       fprintf(fout, "%f ",FRAG(i)); 
     } 

     fprintf(fout, "%f",outreal[i]); 
     if (opt_j) 
      fprintf(fout, "%f",outimag[i]); 
     fprintf(fout, "\n"); 
    } 
    fclose(fout); 

    printf("\nEnd of program\n"); 

    //getchar(); 
    return 0; 
} 
0

आपको लगता है कि उल्लेख "। .. परिवर्तन गलत लग रहा था, ... "

क्या आपने परिणामों की तुलना किसी अन्य प्रोग्राम या सॉफ्टवेयर पैकेज से की है ताकि यह पुष्टि हो सके कि परिणाम वास्तव में गलत हैं? मैंने हाल ही में सी ++ और जावास्क्रिप्ट में एक डीएफटी लिखा है और आउटपुट की तुलना MATLAB, Maple, और MathCAD से परिणामों की तुलना में की है। कभी-कभी अंतर केवल स्केलिंग या स्वरूपण का मामला है।

उन आयामों की मूल सरणी कितनी बड़ी थी जो आप इनपुट करना चाहते थे? यदि आप यहां नमूना डेटा पोस्ट करते हैं, तो मैं इसे अपने प्रोग्राम के माध्यम से चलाने के लिए तैयार हूं और देखता हूं कि मेरा प्रोग्राम आपके जैसा ही परिणाम दिखाता है या नहीं।

संबंधित मुद्दे