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

  • Thread starter Thread starter MathematicalPhysicist
  • Start date Start date
  • Tags Tags
    Code Error
Click For Summary

Discussion Overview

The discussion revolves around a C code implementation of the trapezoid method for numerical integration of the function f(x) = 10x² - x³ over the interval from x = -2.5 to x = 2. Participants are identifying errors and suggesting improvements related to the loop condition, variable types, and formatting in input/output functions.

Discussion Character

  • Technical explanation
  • Debate/contested

Main Points Raised

  • One participant points out that the loop condition does not account for the number of segments, suggesting that it should be independent of the specific function being integrated.
  • Another participant emphasizes the need to use %lf instead of %f for scanf and printf when dealing with long double values, highlighting potential undefined behavior.
  • Concerns are raised about the declaration of Segments as a long double, with suggestions that it should be an unsigned integer since it represents a count of segments.
  • There are discussions about the appropriateness of the loop condition, with suggestions to use a for loop that iterates based on the number of segments.
  • Some participants clarify the correct format specifiers for long doubles in scanf and printf, with conflicting views on whether %Lf must be used.
  • One participant critiques the practice of generating reports inside the loop, suggesting that it should be done after the loop completes.

Areas of Agreement / Disagreement

Participants express differing opinions on the correct usage of format specifiers for long doubles and the structure of the loop. There is no consensus on the best approach to the loop condition or the declaration of variables, indicating multiple competing views remain.

Contextual Notes

Some participants note that the loop condition presumes an answer, which may not be appropriate for all functions. There are also concerns about the handling of floating-point comparisons and the implications of using specific data types for the number of segments.

MathematicalPhysicist
Science Advisor
Gold Member
Messages
4,662
Reaction score
372
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:
#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;
    }
}
 
Technology news on Phys.org
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.
 
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.
 
DH, why should my loop condition should have included the variable 'Segments' ?
 
thanks out of whack, didnt know you should use %lf here.
 
loop quantum gravity said:
DH, why should my loop condition should have included the variable 'Segments' ?

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.
 
out of whack said:
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.

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.
 
D H said:
For scanf, long doubles should be scanned using %Lf, not %lf.

The format "%f" for printf, is correct. %lf is non-standard (undefined behavior)

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).
 
%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.
 
  • #10
D H said:
%Lf can be used but does not have to be used for long doubles passed to printf. Check your standards again

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.
 
  • #11
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.
 
  • #12
D H 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.

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.
 

Similar threads

Replies
1
Views
2K
  • · Replies 4 ·
Replies
4
Views
1K
  • · Replies 4 ·
Replies
4
Views
2K
  • · Replies 22 ·
Replies
22
Views
4K
  • · Replies 1 ·
Replies
1
Views
2K
Replies
14
Views
4K
Replies
7
Views
2K
  • · Replies 8 ·
Replies
8
Views
2K
  • · Replies 5 ·
Replies
5
Views
2K
Replies
47
Views
5K