Search code examples
cfloating-pointstring-formattingtruncate

C program is giving unexpected answer


#include <stdio.h>

int main(){

    float a;

    scanf("%f",&a);
    a=(int)(a*1000+0.5);
    printf("%.5f\n",a);
    a=a/1000;
    printf("%.5f\n",a);

    return 0;
}

This program is written to round off a floating point number up to 3 decimal points in a specific way; e.g. 65.43296 should print as 65.43200, not 65.432.

According to logic it should work but I am getting an unexpected answer like following:

1234.56789        
1234568.00000    
1234.567993

Explain this behaviour.


Solution

  • Although input was "1234.56789", that is only near the value saved in float a.

    float as 32-bit object, can only store exactly about 232 different values. Due to the typical binary encoding of a float, 1234.56789 is not one of those 232. Instead the nearest float is used.

    1234.56787109375   // nearest float's exact value
    1234.56789
    1234.5679931640625 // next nearest float's exact value
    

    a*1000+0.5 can be expected to result in 1234568.375 and (int)(a*1000+0.5) to 1234568.0. So far no great surprise.

    The quotient a/1000; is also a float and since it too is not one of those 232, the result is the nearest float

    1234.5679931640625 // nearest float.
    1234.568           // math result of 1234568.0/1000
    1234.568115234375  // next nearest float
    

    printf("%.5f\n", 1234.5679931640625) is then as seen by OP.

    1234.56799
    

    In general, float will provide expected answers when the number of leading significant digits if 6 or less. OP's expectation of "1234.56800" is 9 digits.


    Had code used double, similar unexpected answers can occur when the number of leading significant digits exceeds 15.