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

• MathematicalPhysicist

MathematicalPhysicist

Gold Member
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;
}
}

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.

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; }

• 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.

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.

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.

%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. 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.

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.

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.