Thread: nan in output

  1. #1
    Registered User
    Join Date
    Dec 2013
    Posts
    26

    nan in output

    Hi there,

    I am having difficulty getting the right output from this program, it just takes some data and works out the rms. However, the input is supposed to be 16-bit data, hence the forcing to int of the test data which of course should really end up as a float. I don't want decimals at that part of the program.

    The program is doing (finally) almost exactly what I am after, but this one bug on some of the output. I think the problem is either:
    declaring my variables incorrectly, I need the variable total to get be 64-bit which I thought was long long.

    or, there is a problem with the square rooting of some of the data that the program is treating as an imaginary number as such.

    Code:
    /* Program to compute the RMS value or 1024 Samples 16-bit 2's comp data. 
    This program has been designed to run a rolling block of samples so 
    that once the initial block of 1024 samples has been aquired the program 
    rms is then calculated each time a new sample is added and the oldest sample
    is removed from the block*/
    #include <stdio.h>
    #include <math.h> // Library required for using sqrt function
    
    #define MAX 10 // sample block, in this case 1024
    #define DATA 50 // size of test data
    
    //function to calculate rms and print output to screen
    float rms(long total)
    { 
         printf("rms = %f\n", sqrt(total / MAX));
         return 0;
    }
    
    /* Function to accept input into the program. The input is stored as a 
    squared number to simplify the process of swapping the oldest sample 
    with the newest sample. */
    void input(long samples[]) 
    {
         int i = 0;
         int j = 0;
         int value;
         long long total;
         int test[DATA];
    
         for (j = 0; j < DATA; ++j) { // This loop supplies test data to mimic 
          test[j] = 324 * sin(j); // input from circuit.
          printf("%d\n", test[j]);
         }
    
         while (i < DATA) {
          total -= samples[i]; // Removes oldest sample from array
          value = test[j];     // Gets new data, in this case from the array "test".
          samples[i] = value * value;
          total += samples[i];
          rms(total);
          ++j;
         }
    }
    
    // Function to initialize array for 1024 samples
    void init()
    {
         int i;
         long samples[MAX];
     
         for (i = 0; i < MAX; ++i) {
          samples[i] = 0;
         }
         input(samples);
    }
    
    // Program start
    int main(void)
    {
         init();
         return 0;
    }
    Kind regards

    P166

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    This loop appears to be an infinite loop as i is unchanged in the loop:
    Code:
         while (i < DATA) {
          total -= samples[i]; // Removes oldest sample from array
          value = test[j];     // Gets new data, in this case from the array "test".
          samples[i] = value * value;
          total += samples[i];
          rms(total);
          ++j;
         }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Dec 2013
    Posts
    26
    Oh yes of course. Well I've fixed this as best I could, but the nan error is still there and I am getting a Segmentation Fault 11 also.

    What I am trying to do, si use a rolling array of at the moment 10, that will pass through 50 lines of data. This is to be scaled up to 1024 samples with at least twice the amount for test data. But at present I am using two arrays of 10 and 50. As far as I am aware, a segmentation fault is trying to access unallocated memory. So either I am going outside the bounds of my arrays or the numbers are getting larger than the assignment types I am giving them. Here is the current program.
    Code:
    /* Program to compute the RMS value or 1024 Samples 16-bit 2's comp data. 
    This program has been designed to run a rolling block of samples so 
    that once the initial block of 1024 samples has been aquired the program 
    rms is then calculated each time a new sample is added and the oldest sample
    is removed from the block*/
    #include <stdio.h>
    #include <math.h> // Library required for using sqrt function
    
    #define MAX 10 // sample block, in this case 1024
    #define DATA 50 // size of test data
    
    //function to calculate rms and print output to screen
    float rms(long total)
    { 
         printf("rms = %f\n", sqrt(total / MAX));
         return 0;
    }
    
    /* Function to accept input into the program. The input is stored as a 
    squared number to simplify the process of swapping the oldest sample 
    with the newest sample. */
    void input(long samples[]) 
    {
         int i = 0;
         int j = 0;
         int value;
         long long total;
         int test[DATA];
    
         for (j = 0; j < DATA; ++j) { // This loop supplies test data to mimic 
          test[j] = 324 * sin(j); // input from circuit.
          printf("%d\n", test[j]);
         }
    
         while (i < DATA) {
          if (i < MAX) {
               total -= samples[i]; // Removes oldest sample from array
               value = test[j];     // Gets new data, in this case from the array "test".
               samples[i] = value * value;
               total += samples[i];
               rms(total);
               ++j;
               ++i;
          }
          else
               i = 0;
         }
    }
    
    // Function to initialize array for 1024 samples
    void init()
    {
         int i;
         long samples[MAX];
     
         for (i = 0; i < MAX; ++i) {
          samples[i] = 0;
         }
         input(samples);
    }
    
    // Program start
    int main(void)
    {
         init();
         return 0;
    }

  4. #4
    Registered User
    Join Date
    Dec 2013
    Posts
    26
    ok, this is more serious than I thought. This program was running correctly, until I tried to scale it up to roll through the samples. I have just set the variable of j = 10 as the only input to the program, so the result should start at about 3. something, and soon get to 10 and stay at 10, why am I getting 4429.198799?

  5. #5
    Registered User
    Join Date
    Dec 2013
    Posts
    26
    Right, I have rethought the input function into a slightly more logical structure and it seems to work now. I would still value peoples input as to whether I am missing something.

    Am I right in that the previous code was messing with the arrays and accessing them out of their range?

    Code:
    /* Program to compute the RMS value or 1024 Samples 16-bit 2's comp data. 
    This program has been designed to run a rolling block of samples so 
    that once the initial block of 1024 samples has been aquired the program 
    rms is then calculated each time a new sample is added and the oldest sample
    is removed from the block*/
    #include <stdio.h>
    #include <math.h> // Library required for using sqrt function
    
    #define MAX 10 // sample block, in this case 1024
    #define DATA 50 // size of test data
    
    //function to calculate rms and print output to screen
    float rms(long total)
    { 
         printf("rms = %f\n", sqrt(total / MAX));
         return 0;
    }
    
    /* Function to accept input into the program. The input is stored as a 
    squared number to simplify the process of swapping the oldest sample 
    with the newest sample. */
    void input(long samples[]) 
    {
         int i;
         int j;
         int value;
         long total;
         int test[DATA];
    
    /* This for loop is here to represent input data to the program from a circuit.
    a sine wave with an amplitude of 340 has been used with the expected result of 
    around 240, the same as UK mains voltage. */
         for (j = 0; j < DATA; ++j) {  
          test[j] = 340 * sin(j); 
          printf("%d\n", test[j]);
         }
    
         j = 0;
         while (j < DATA) {
          for (i = 0; i < MAX; ++i) {
               total -= samples[i]; // Removes oldest sample from array
               value = test[i];     // Gets new data, in this case from the array "test".
               samples[i] = value * value;
               total += samples[i];
               rms(total);
          }
          ++j;
         }
    }
    
    // Function to initialize array for 1024 samples
    void init()
    {
         int i;
         long samples[MAX];
     
         for (i = 0; i < MAX; ++i) {
          samples[i] = 0;
         }
         input(samples);
    }
    
    // Program start
    int main(void)
    {
         init();
         return 0;
    }
    Kind regards

    P166

  6. #6
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Your logic is completely wrong. You have a double (nested) loop, whereas you clearly need a single loop.


    Your program structure is also strange. A function called "init" usually "initializes" a program. Yours does everything.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  7. #7
    Registered User
    Join Date
    Dec 2013
    Posts
    26
    Yes definitely memory problems, as soon as I put set the amount of samples to 1024, the result comes in at 370725.something. I am expecting 230.something.

    What am I doing wrong?

  8. #8
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    There's a number of things wrong with it. I'd scrap this code (it's a very small program) and start again. Don't bother with the comments for now as they just get in the way at this point.

    Firstly there's your names. What does "MAX" mean? When you figure that out, rename it so that others know too. Same with "DATA". How about BLOCK_SIZE and NUM_SAMPLES?

    Also, there's no need to pregenerate and store all of the samples since they are calculable from the index alone.

    Don't use a long (or long long). Just use a double since you're dealing with a sin, which has a fractional part.

    Another problem is that you're generating your samples by taking the sin of 0, 1, 2, etc. The sin function takes radians, so it's like taking the sin of 0 degrees, about 60 degrees, about 120, etc. Is that what you want? What is the angular interval for the samples?

    Yet another problem is that you're treating a one-dimensional problem as a two-dimensional problem. There's a certain number of samples (NUM_SAMPLES) and you want to go through all of them once. Within that loop you also need to deal with an index into your block, but that index should not be dealt with in it's own loop. It should be something like:
    Code:
    i = 0;
    for (j = 0; j < NUM_SAMPLES; ++j) {
    
        /* ... other stuff ... */
    
        if (i >= BLOCK_SIZE)
            i = 0;
    }
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  9. #9
    Registered User
    Join Date
    Dec 2013
    Posts
    26
    Yes you are absolutely correct there are a few things wrong with that for loop for sine. But as it is doing it's job perfectly, it giving me 16-bit signed values ranging from 0 up to 324 and back down the other way, it is suffice. This is not the problem.

    The problem is that if the sample rate is kept below 300, I get a perfect result approximately 221.743 This is the correct result for this calculation.

    If I change MAX which is the size of my samples, to 1024, the result is wrong it is 370725.1206. I am curious to know why this is happening. I am sure it is not my sine wave with the decimal values omitted.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Copying input to output K&R there is no output
    By amadeus111 in forum C Programming
    Replies: 5
    Last Post: 02-24-2013, 05:09 AM
  2. C++ overlapping output and adding extensions to output files
    By lordmorgul in forum Linux Programming
    Replies: 9
    Last Post: 05-11-2010, 08:26 AM
  3. How to edit output in struct and call for the output
    By andrewkho in forum C Programming
    Replies: 4
    Last Post: 03-16-2010, 10:28 PM
  4. terminal output not showing output properly
    By stanlvw in forum C Programming
    Replies: 13
    Last Post: 11-19-2007, 10:46 PM
  5. Replies: 3
    Last Post: 02-19-2003, 08:34 PM

Tags for this Thread