Jump to content

Trying to draw a sine wave in C

- - - - -

  • Please log in to reply
13 replies to this topic

#1
Yuriy M

Yuriy M

    Learning Programmer

  • Members
  • PipPipPip
  • 70 posts
Hi guys. I'm hoping that I can get help on a really stubborn problem that I've been having lately.

I'm doing a C program that involves printing out a sine wave using the "*" character. The main coding is complete but for some strange reason the "*"'s just won't display on the screen. All I'm getting is blanks. Here's my code:

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

int main(void)
{
    /* Declare variables */
    
    int    line_count,              /* Counts the lines in the program */
           no_of_lines;             /* The number of lines to display in the graph */
    double result,                  /* The sine result from the calculation */
           initial_step_size,       /* The initial step size in degrees */
           current_step_size,       /* The current step size in degrees */ 
           sine_count;              /* Counts the values in the sine range */
    
    /* Prompt user for information */
    
    printf("\nEnter the initial step-size in degrees: ");
    scanf("%lf", &initial_step_size);
    printf("\nEnter the number of lines to be displayed in the graph: ");
    scanf("%d", &no_of_lines);
    
    /* Assign to current step size */
    
    current_step_size = initial_step_size;
    
    /* Display graph */
    
    for (line_count = 0; line_count < no_of_lines; line_count++)
    {
     result = sin(current_step_size);
     for (sine_count = -1; sine_count <= 1; sine_count += 0.01)
     {
      if (result == sine_count)
       printf("\n*\n");
      else
       printf(" "); 

     }
     /* Increment step size */
     current_step_size += initial_step_size;         
    }
    
    return 0;   
}
Both for loops run well and displayed the necessary values during tests. The only problem left is the if condition that is supposed to compare the calculated sin result with the sine range value. Basically, if the result matches the sine range value, display a star. Otherwise, display a blank. Is it a problem with my code? Or is it possible that it may be a problem with my compiler?

Any help will be appreciated. Thanks! :)
For $1000: Something that is a miserable pile of secrets.

#2
gregwarner

gregwarner

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 853 posts
  • Location:Arkansas
I see 2 problems:


if (result == sine_count)


You're stepping by 0.01 increments, but since you're checking for exact equivalence, you're likely to never get an exact match. A better approach here would be to check whether the sin of current_step_size falls within a margin of 0.01.

Second:


printf("\n*\n");


I'm not sure what your intent was here, but it looks like all the asterisks are going to be at the beginning of the line, since you have a newline before it. The asterisks won't form a sin wave at all.
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.

– Douglas Hofstadter, Gödel, Escher, Bach: An Eternal Golden Braid


#3
Yuriy M

Yuriy M

    Learning Programmer

  • Members
  • PipPipPip
  • 70 posts

gregwarner said:

You're stepping by 0.01 increments, but since you're checking for exact equivalence, you're likely to never get an exact match. A better approach here would be to check whether the sin of current_step_size falls within a margin of 0.01.
I'll give that a shot. Thanks. :)

Quote

I'm not sure what your intent was here, but it looks like all the asterisks are going to be at the beginning of the line, since you have a newline before it. The asterisks won't form a sin wave at all.
Compare sine_count value to result. If the match is found, print a star. Otherwise, print a blank. Move on to the next sine_count value and repeat.
For $1000: Something that is a miserable pile of secrets.

#4
gregwarner

gregwarner

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 853 posts
  • Location:Arkansas
You shouldn't print a newline before the star then, only after. You'll also need to break out of the for loop so that the program flow will continue with the next line, or else your spaces will be off because it will print the rest of the spaces for that line on the next line.
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.

– Douglas Hofstadter, Gödel, Escher, Bach: An Eternal Golden Braid


#5
gregwarner

gregwarner

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 853 posts
  • Location:Arkansas
It should also be noted that math.h operates in Radians, not Degrees.
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.

– Douglas Hofstadter, Gödel, Escher, Bach: An Eternal Golden Braid


#6
gregwarner

gregwarner

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 853 posts
  • Location:Arkansas
I also adjusted the step size from 0.01 to 0.05. I compiled the adjustments that I mentioned above and got it to work with these results:

Enter the initial step-size in radians: 0.4


Enter the number of lines to be displayed in the graph: 16

                           *

                                  *

                                      *

                                       *

                                      *

                                 *

                          *

                  *

           *

    *

*

*

  *

       *

              *

                      *


Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.

– Douglas Hofstadter, Gödel, Escher, Bach: An Eternal Golden Braid


#7
Yuriy M

Yuriy M

    Learning Programmer

  • Members
  • PipPipPip
  • 70 posts
Here is my improvement on the program so far. It's still not 100% complete yet but it's better than the previous version I put up:
#include <stdio.h>
#include <math.h>

int main(void)
{
    /* Declare variables */
    
    int    line_count,              /* Counts the lines in the program */
           sine_count,              /* Counts the values in the sine range */
           no_of_lines;             /* The number of lines to display in the graph */
    double result,                  /* The resulting sine value */
           initial_step_size,       /* The initial step size in degrees */
           current_step_size;       /* The current step size in degrees */ 
    
    /* Prompt user for information */
    
    printf("\nEnter the initial step-size in degrees: ");
    scanf("%lf", &initial_step_size);
    printf("\nEnter the number of lines to be displayed in the graph: ");
    scanf("%d", &no_of_lines);
    
    /* Convert from degrees to radians and assign to current step size */
    
    current_step_size = initial_step_size * 3.14 / 180;
    printf("\n");
 
    /* Display graph */
    
    for (line_count = 0; line_count < no_of_lines; line_count++)
    {
     result = sin(current_step_size);
     for (sine_count = -90; sine_count <= 90; sine_count++)
     {
      if (result == sin(sine_count * 3.14 / 180))
      {
       printf("*");
       break;
      }
      else
       printf(" ");
     }  
     /* Increment step size */
     
     current_step_size += initial_step_size * 3.14 / 180;    
     printf("\n");     
    }
   
    return 0;   
}
The output of the program only seems to generate an upwards slope rather than the wave I was expecting but I am getting close.
For $1000: Something that is a miserable pile of secrets.

#8
Yuriy M

Yuriy M

    Learning Programmer

  • Members
  • PipPipPip
  • 70 posts
I think I have it working now:

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

int main(void)
{
    /* Declare variables */
    
    int    line_count,              /* Counts the lines in the program */
           sine_count,              /* Counts the values in the sine range */
           no_of_lines,             /* The number of lines to display in the graph */
           initial_step_size;       /* The initial step size in degrees */
    double current_step_size;       /* The current step size in degrees */ 
    
    /* Prompt user for information */
    
    printf("\nEnter the initial step-size in degrees: ");
    scanf("%d", &initial_step_size);
    printf("\nEnter the number of lines to be displayed in the graph: ");
    scanf("%d", &no_of_lines);
    
    /* Convert from degrees to radians and assign to current step size */
    
    current_step_size = initial_step_size * 3.14 / 180;

    /* Display graph */
    
    for (line_count = 0; line_count < no_of_lines; line_count++)
    {
     for (sine_count = -90; sine_count <= 90; sine_count++)
     {
      /* Compare the sin of the step value to the sin of the sine range value and print '*' if there is a match.
         Otherwise, print a blank */
      if (sin(current_step_size) == sin(sine_count * 3.14 / 180))
      {
       printf("*");
       break;
      }
      else
       printf(" ");
     }  
     /* Increment step size */
     current_step_size += initial_step_size * 3.14 / 180;  
    }
   
    return 0;   
}

The wave seems to appear normally when I enter single digit degree values but expands upon larger degree values. However, my command prompt won't allow me to expand the window to make sure that a wave is being printed properly. I am now in need of a second opinion. Is the program sufficient to print out the sine wave?
For $1000: Something that is a miserable pile of secrets.

#9
gregwarner

gregwarner

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 853 posts
  • Location:Arkansas

Yuriy M said:

The wave seems to appear normally when I enter single digit degree values but expands upon larger degree values. However, my command prompt won't allow me to expand the window to make sure that a wave is being printed properly.

This is the exact reason why I did this:

Quote

I also adjusted the step size from 0.01 to 0.05.

In your inner for loop, you are looping from -90 to 90, inclusive, a total of 181 iterations, printing a single character each time, however, your console window is only 80 characters wide. Use a step value greater than 1 in order to reduce your total number of iterations here to 80 or fewer.
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.

– Douglas Hofstadter, Gödel, Escher, Bach: An Eternal Golden Braid


#10
Yuriy M

Yuriy M

    Learning Programmer

  • Members
  • PipPipPip
  • 70 posts

gregwarner said:

You're stepping by 0.01 increments, but since you're checking for exact equivalence, you're likely to never get an exact match. A better approach here would be to check whether the sin of current_step_size falls within a margin of 0.01.
By that point, would it suffice to use the conditional statement:
if (current_step_size > 0.01 && current_step_size <= 0.02)
 printf("*\n");
else
 printf(" ");

For $1000: Something that is a miserable pile of secrets.

#11
gregwarner

gregwarner

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 853 posts
  • Location:Arkansas
No, the way I would do it is like this:


// Declare yourself a constant like this to define the sample size

const double sample_size = 0.05; // This is the 0.05 sample size I was mentioning before, to make sure the line doesn't exceed 80 characters.


...


// Your inner for loop:

result = sin(current_step_size);

for (sine_count = -1; sine_count <= 1; sine_count += sample_size)

{

    // Here is where you test to see if the result falls within the range of the sample size:

    // sine_count is the lower bound of that range, and (sine_count + sample_size) is the upper bound.

    if (result >= sine_count && result < (sine_count + sample_size))

        printf("*\n");

    else

        printf(" ");

}


Do you understand better how that works?

Edited by gregwarner, 20 July 2011 - 07:46 AM.

Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.

– Douglas Hofstadter, Gödel, Escher, Bach: An Eternal Golden Braid


#12
Yuriy M

Yuriy M

    Learning Programmer

  • Members
  • PipPipPip
  • 70 posts
Much better! The program is now working beautifully! Thanks for all your help, Greg! :w00t:

P.S. Trigonometry was also not one of my strong points when it came to learning mathematics so that was also why it took me as long as it did to get this program working. Once again, thanks a lot, Greg! :)
For $1000: Something that is a miserable pile of secrets.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users