Same numerical code returns different output whether it is in C++ or C

85 views Asked by At

I was given an example C++ numerical code calculating derivatives in three different ways. I have to convert it to C. I thought it wouldn't give me any problems due to original using cmath anyway, but I was so wrong. Here is the original code:

#include <iostream>
#include<string>
#include <cmath>
#include <fstream>
using namespace std;


double metoda_pochodna_1(int x, double h)
{
    return (sin(x+h) - sin(x)) / h;
}   
double metoda_pochodna_2(int x, double h)
{
    return (sin(x+(0.5*h)) - sin(x-(0.5*h))) / h;
}
double metoda_pochodna_3(int x, double h)
{
    return ((sin(x-2*h) - 8*sin(x-h) + 8*sin(x+h) - sin(x+2*h)) / (12*h));
}


int main()
{
    double h, w1, w2, w3, kos = cos(1.0);
    int x=1;
    ofstream wyniki;
    wyniki.open("wyniki.dat");

    for (h = pow(10.0, -15.0); h < 1; h *= 1.01) 
    {
        w1 = log10(abs(metoda_pochodna_1(x,h) - kos));
        w2 = log10(abs(metoda_pochodna_2(x,h) - kos));
        w3 = log10(abs(metoda_pochodna_3(x,h) - kos));
        wyniki << log10(h)<<"  "<< w1 <<"  "<< w2 <<"  "<< w3 << "\n";
        cout << log10(h)<<"  "<< w1 <<"  "<< w2 <<"  "<< w3 << "\n";
    }

    wyniki.close();
    cout << endl;
    /*system("pause");*/ //uruchamiane z windowsa
    return 0;
}

And here is my C version; I just changed file handling. NOTE: I changed to long double during troubleshooting , but the resulting output is exactly the same as the version using regular double.

#include <math.h>
#include <stdio.h>
#include <stdlib.h>



long double metoda_pochodna_1(int x,long  double h)
{
    return (sin(x+h) - sin(x)) / h;
}   
long double metoda_pochodna_2(int x,long  double h)
{
    return (sin(x+(0.5*h)) - sin(x-(0.5*h))) / h;
}
long double metoda_pochodna_3(int x, long double h)
{
    return ((sin(x-2*h) - 8*sin(x-h) + 8*sin(x+h) - sin(x+2*h)) / (12*h));
}


int main()
{
    long double h, w1, w2, w3, kos = cos(1.0);
    int x=1;
    FILE * file;
    file = fopen("wyniki.dat","w+");


    for (h = pow(10.0, -15.0); h < 1; h *= 1.01) 
    {
        w1 = log10(abs(metoda_pochodna_1(x,h) - kos));
        w2 = log10(abs(metoda_pochodna_2(x,h) - kos));
        w3 = log10(abs(metoda_pochodna_3(x,h) - kos));
        fprintf(file,"%f %Lf %Lf %Lf\n",log10(h), w1,w2,w3);
        printf("%f %Lf %Lf %Lf\n",log10(h), w1,w2,w3);
        //wyniki << log10(h)<<"  "<< w1 <<"  "<< w2 <<"  "<< w3 << "\n";
        //cout << log10(h)<<"  "<< w1 <<"  "<< w2 <<"  "<< w3 << "\n";
    }

    fclose(file);
    printf("\n");
    return 0;
}

This is the output of the C++ code, which I am assuming correct:

-15  -1.82947  -1.82947  -1.28553

-14.9957  -2.03091  -2.03091  -1.33768

14.9914  -2.41214  -2.41214  -1.39632

-14.987  -2.81915  -2.81915  -1.46341

[...]

And this is the output of the C version, which obviously differs (additional precision in front row is from long double, but the other three columns are all -inf regardless of whether double or long double is used):

-15.000000 -inf -inf -inf

-14.995679 -inf -inf -inf

-14.991357 -inf -inf -inf

-14.987036 -inf -inf -inf

[...]

What is wrong with my converted code?

1

There are 1 answers

1
Weather Vane On BEST ANSWER

You are using abs which is an integer function. The C floating point function is fabs. After changing your three lines to

w1 = log10(fabs(metoda_pochodna_1(x,h) - kos));
w2 = log10(fabs(metoda_pochodna_2(x,h) - kos));
w3 = log10(fabs(metoda_pochodna_3(x,h) - kos));

the program outputs more sensible values.