Search code examples
cfloating-pointfloating-point-precision

Strange output when using float instead of double


Strange output when I use float instead of double

#include <stdio.h>
void main()
{
    double p,p1,cost,cost1=30;
    for (p = 0.1; p < 10;p=p+0.1)
    {
        cost = 30-6*p+p*p;
        if (cost<cost1)
        {
            cost1=cost;
            p1=p;
        }
        else
        {
            break;
        }
        printf("%lf\t%lf\n",p,cost);
    }
    printf("%lf\t%lf\n",p1,cost1);
}

As Expected

Gives output as expected at p = 3;

But when I use float the output is a little weird.

#include <stdio.h>
void main()
{
    float p,p1,cost,cost1=40;
    for (p = 0.1; p < 10;p=p+0.1)
    {
        cost = 30-6*p+p*p;
        if (cost<cost1)
        {
            cost1=cost;
            p1=p;
        }
        else
        {
            break;
        }
        printf("%f\t%f\n",p,cost);
    }
    printf("%f\t%f\n",p1,cost1);
}

Strange increment style

Why is the increment of p in the second case going weird after 2.7?


Solution

  • This is happening because the float and double data types store numbers in base 2. Most base-10 numbers can’t be stored exactly. Rounding errors add up much more quickly when using floats. Outside of embedded applications with limited memory, it’s generally better, or at least easier, to use doubles for this reason.

    To see this happening for double types, consider the output of this code:

    #include <stdio.h>
    int main(void)
    {
        double d = 0.0;
        for (int i = 0; i < 100000000; i++)
            d += 0.1;
        printf("%f\n", d);
        return 0;
    }
    

    On my computer, it outputs 9999999.981129. So after 100 million iterations, rounding error made a difference of 0.018871 in the result.

    For more information about how floating-point data types work, read What Every Computer Scientist Should Know About Floating-Point Arithmetic. Or, as akira mentioned in a comment, see the Floating-Point Guide.