3
\$\begingroup\$

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;
}
\$\endgroup\$
  • \$\begingroup\$ im confused for why you are mallocing doubles when there is no need for it \$\endgroup\$ – downrep_nation Sep 7 '17 at 21:53
3
\$\begingroup\$
  1. 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

  1. 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");
    
  2. The various calls to like code suggest that a helper print function should be written.

  3. For printing double, I find %e more informative than %f.

  4. 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 least size_t width. Checking for a NULL allocation makes for robust code.

    // sum = malloc(GRADE * sizeof(double));
    sum = malloc(sizeof *sum * GRADE);
    if (sum == NULL) TBD();
    
  5. 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)
    
  6. Help convey the double-ness of the variable.

    // sum[j] = 0;  // This looks `int`-ish
    sum[j] = 0.0;
    
\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.