I had to write a program to calculate the Lagrange polynomial of the maddening degree of function: \$\log(x+1)+\cos(x-1)\$
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define GRADE 6
/* Funzione per costruire la successione dei nodi (xi,yi) dei punti di valutazione*/
void nodeSuccession(double* xNode, double* yNode, double* xVal){
int i;
printf("xNode [");
for(i = 0; i < GRADE + 1; i++){
xNode[i] = i; /* Array contenete le ascisse dei nodi */
printf("%.4f, ", xNode[i]);
yNode[i] = 0; /* Array contenete le ordinate dei nodi */
}
printf("\b\b]\n");
printf("yNode [");
for(i = 0; i < GRADE + 1; i++){
yNode[i] = (log(xNode[i] + 1)) + cos(xNode[i] - 1);
printf("%.4f, ", yNode[i]);
}
printf("\b\b]\n");
printf("xVal [");
for(i = 0; i < GRADE; i++){
xVal[i] = (xNode[i] + xNode[i+1]) / 2;
printf("%.4f, ", xVal[i]);
}
printf("\b\b]\n");
}
/* Funzione per costruire il polinomio di lagrange e lo valuto nei punti */
double* polynomial(double *xVal, double *xNode, double *yNode){
int i, j, k;
double pr, *sum = malloc(GRADE * sizeof(double));
for(j = 0; j < GRADE; j++){
sum[j] = 0;
for(k = 0; k < GRADE + 1; k++){
pr = 1;
for(i = 0; i < GRADE + 1; i++){
if(k != i)
pr = pr * ((xVal[j] - xNode[i])/(xNode[k] - xNode[i]));
}
sum[j] = sum[j] + yNode[k] * pr;
}
}
return sum;
}
/* Funzione per la valutazione dell'errore di interpolazione */
double* error(double *xVal, double *sum){
int i;
double *err = malloc(GRADE * sizeof(double));
for(i = 0; i < GRADE; i++)
err[i] = fabs(((log(xVal[i] + 1)) + cos(xVal[i] - 1)) - sum[i]);
return err;
}
int main(void){
int i;
double xNode[GRADE + 1], xVal[GRADE], yNode[GRADE + 1];
double *poly = malloc(GRADE * sizeof(double)), *err = malloc(GRADE * sizeof(double));
system("clear");
printf("\n===== PROGRAMMA PER IL CALCOLO DEL POLINOMIO DI LAGRANGE =====\n\n");
nodeSuccession(xNode, yNode, xVal);
poly = polynomial(xVal, xNode, yNode);
printf("\npoly [");
for(i = 0; i < GRADE; i++)
printf("%.4f, ", poly[i]);
printf("\b\b]\n");
err = error(xVal, poly);
printf("err [");
for(i = 0; i < GRADE; i++)
printf("%.4f, ", err[i]);
printf("\b\b]\n");
free(poly);
free(err);
return 0;
}
-
\$\begingroup\$ im confused for why you are mallocing doubles when there is no need for it \$\endgroup\$downrep_nation– downrep_nation2017年09月07日 21:53:36 +00:00Commented Sep 7, 2017 at 21:53
2 Answers 2
Consider passing in the array size rather than fixing it at 6 in the
polynomial(), nodeSuccession()
functions.// polynomial(xVal, xNode, yNode) polynomial(6, xVal, xNode, yNode)
Minor stuff
Two backspaces may not truly "back-space". Less problematic to not print unwanted text. Various solutions. Perhaps as below.
const char *separator = ""; printf("xNode ["); for (i = 0; i < GRADE + 1; i++) { xNode[i] = i; printf("%s%.4f", separator, xNode[i]); yNode[i] = 0; separator = ", "; } printf("\n");
The various calls to like code suggest that a helper print function should be written.
For printing
double
, I find%e
more informative than%f
.Rather than allocate to the size of the type, allocate to the size of the de-referenced pointer. It easier to code correctly, review and maintain. Putting the
sizeof
part first insures any integer math is done with at leastsize_t
width. Checking for aNULL
allocation makes for robust code.// sum = malloc(GRADE * sizeof(double)); sum = malloc(sizeof *sum * GRADE); if (sum == NULL) TBD();
Use
const
with the pointers to insure wider application of the function and allow optimizations the compiler may not readily recognize.// double* polynomial(double *xVal, double *xNode, double *yNode){ double* polynomial(const double *xVal, const double *xNode, const double *yNode){ // double* error(double *xVal, double *sum) double* error(const double *xVal, const double *sum)
Help convey the
double
-ness of the variable.// sum[j] = 0; // This looks `int`-ish sum[j] = 0.0;
As a general principle, I find it annoying when programs do this:
system("clear");
printf("\n===== PROGRAMMA PER IL CALCOLO DEL POLINOMIO DI LAGRANGE =====\n\n");
The second (i.e. print) is only a minor annoyance: I've just started the program, so why do I need telling what it is? It does mean that I need to filter out that message if I want to pipe the results to another program.
The first (i.e. clear) is much more serious. If I want a clear screen (and assuming that the output is going to a device where that actually means something), I can do that as a user. If I want to keep the previous results visible, the program has denied me that option. All assuming that the system has a working "clear" command - IIRC, there are (non-POSIX) systems that don't.
This version of the program doesn't accept arguments, but when it does, then the clear
makes it much harder to compare different invocations, because the previous results are always obliterated.
I recommend writing only the actual output to standard output, and nothing to standard error unless the program has not performed its task (when it should exit with a non-zero status).
And please get into the habit of checking the return value of printf()
. It's annoying for programs to report success when actually the file system that their output is connected to has filled up, and nothing was actually written.