Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Spot the error in my code. (in C).

  1. Apr 3, 2007 #1
    i was asked to write down a code that calculates via the trapezoid method, the integral f(x)=10x^2-x^3 from x=-2.5 up to x=2, and compares it to the analytic solution. well here's my code, my problem is that it's stuck on numbers such as 20 (number of segments).
    can anyone spot my error in my code, i appreciate:
    Code (Text):

    #include <stdio.h>
    #include <math.h>
    main()
    {
      long double initial,area,Segments,dx;
      initial=-2.5;
      area=0;
      printf("insert the number of sgements to subdivide the interval \n");
      scanf("%f", &Segments);
      if(Segments!=0) dx=4.5/Segments;
      else printf("error \n");
      while(area<=84.515625 && initial<2)
        {
          area+=0.5*dx*((initial+dx)*(initial+dx)*10-(initial+dx)*(initial+dx)*(initial+dx)+initial*initial*10-initial*initial*initial);
          if((fabs(area-84.515625))<0.001){
            printf("the numerical integration yields %f with accuracy of 0.001 from analytical result \n",area);
            break;
          }
       
          initial+=dx;
        }
    }
     
  2. jcsd
  3. Apr 3, 2007 #2

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    This is a terrible loop condition:

    while(area<=84.515625 && initial<2)​


    This condition does not involve the number of intervals (i.e., your variable "Segments") at all.
     
  4. Apr 3, 2007 #3
    You process long double values. You should use %lf instead of just %f in scanf and printf. If your system uses different sizes for these types then scanf will store your input using the format you indicate, which is not the format you are actually using. Your program behavior will be undefined.
     
  5. Apr 4, 2007 #4
    DH, why should my loop condition should have included the variable 'Segments' ?
     
  6. Apr 4, 2007 #5
    thanks out of whack, didnt know you should use %lf here.
     
  7. Apr 4, 2007 #6

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    Both clauses are examples of "bad programming" techniques. The first clause, area<=84.515625, presumes an answer. Suppose you wanted to estimate the area under a curve to which you don't know the answer? The loop condition should be independent of the specific function to be integrated.

    The second clause, initial<2, is a little better but still has some problems. A couple minor problems first: The comparand 2 should be 2.0, not 2. A variable would be even better. The big problem is that you might make an extra step because of the way real numbers are approximated on a computer. You can correct this by comparing initial to 2.0-epsilon, where epsilon is some small number.

    An even better approach is to take advantage of the fact that you know exactly how many times the body of the loop should be executed: it is the number of Segments.

    for (i=0; i<Segments; i++) { body; }

    Additional comments:
    • Segments should not be declared as a "long double". How would your program behave if the user specified 3.1415926536 Segments? The trapezoid method requires number of segments be a positive integer. What C data type comes closest to this?
    • For that matter, why is anything declared as a "long double"? Doubles have about 15 decimal places of accuracy, which is far more than you need.
    • Why are you changing the value of "initial"? (The variable name disagrees with its use.)
    • You are generating the final report inside the loop. Bad style, again. This should be done outside the loop, and the report should be generated for all cases. (You do want to know that some choices are bad choices, don't you?)

    Some pseudocode:

    unsigned int n_segments, iseg;
    double x_init, x_end, x, dx;

    // Get integration limits (x_init, x_end) and number of steps (n_segments).

    dx = (x_init-x_end)/n_segments;
    area = 0.0;
    for (iseg = 0; iseg < n_segments; iseg++) {
    // Calculate start of the iseg interval.
    // Estimate area contribution from this segment.
    }
    // Generate report.
     
  8. Apr 4, 2007 #7

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    For scanf, long doubles should be scanned using %Lf, not %lf.

    The format "%f" for printf, is correct. %lf is non-standard (undefined behavior), although most systems interpret "%lf" as "the stupid user meant %f". Printf is a varargs funtion, so all arguments are converted according to ancient C function-call rules: arguments are passed as ints, doubles, or pointers. In particular, a long double (or a float) is converted to a double in the call to printf.
     
  9. Apr 4, 2007 #8
    My mistake: it is indeed %Lf for long double and not %lf. And %Lf is standard for printf as well, as specified in ISO/IEC 9899 (I've just double checked).
     
  10. Apr 4, 2007 #9

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    %Lf can be used but does not have to be used for long doubles passed to printf. Check your standards again, this time looking for how default argument promotions works with the arguments corresponding to the ellipsis in variable argument functions. A long double is converted to a double at the function call. The %Lf format will work whether you call printf with a float, double, or long double value because what is actually passed is a double.
     
  11. Apr 4, 2007 #10
    No need to check the standard again. :rolleyes: It really does say what I said: %Lf is also useable with printf. Its behavior is defined. The standard also says plenty of other things, you've mentioned some of them.

    One benefit of supporting %Lf in both scanf and printf is to let the programmer use a single format string for both input and output, which is handy at times.
     
  12. Apr 4, 2007 #11

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    Yes, the standard says what you said: %Lf can be used with printf. Isn't that exactly what I said? Where I disagree with you is your prior post where you implied %Lf must be used when you pass a long double to printf. You are not really passing a long double to printf, you are passing a plain old vanilla double thanks to C's default argument promotion rules.
     
  13. Apr 4, 2007 #12
    Sorry, I thought you were replying to the post above yours, not the one you had previously replied to. Of course, I agree that even though %Lf is legal syntax in printf, it is not the only valid option. I find that the same data types call for the same specifiers for consistency and self documentation, but this is a personal preference. Your own preference may differ. I think we all got it straight now.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?



Similar Discussions: Spot the error in my code. (in C).
  1. Critique my C++ code (Replies: 11)

Loading...