Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Number precision error in C

Here is a code I wrote:

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

int main()
{
    double num;
    int tmp;
    printf("enter a number!\n");
    scanf("%lf",&num);
    tmp=num*10000;
    printf(" temp=%d\n",tmp);

    return 0; 
}

When I enter the number 1441.1441 the result i'm getting is 14411440 instead of 14411441 which is obviously the correct result after multiplying my input number by 10000. Can someone help me figure out this problem?

like image 782
Rona Hirsch Avatar asked Nov 23 '12 08:11

Rona Hirsch


1 Answers

Since the vast majority of real numbers cannot actually be represented exactly, you'll probably find that 1441.1441 is actually stored as something like 1441.14409999_blah_blah_blah. You can find that out by inserting:

printf ("%.50lf\n", num);

immediately after the scanf and seeing (trailing zeroes removed):

1441.14409999999998035491444170475006103515625

Now that's actually the correct (ie, closest) value based on your input. The next highest number from there gives you:

1441.144100000000207728589884936809539794921875

The error with the first value is:

0.00000000000001964508555829524993896484375
               ^ ~ 2 x 10^-14

while the error with the second is:

0.000000000000207728589884936809539794921875
              ^ ~ 2 x 10^-13

and you can see the latter error is about 10 times as much.

When you multiply that by 10000 and try to shoehorn it into an int, it gets rounded down (truncated). That's because the (C11) standard has this to say in 6.3.1.4:

When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero).

One thing you can try is to change your shoehorning line into:

tmp = num * 10000 + 0.5;

which effectively turns the truncation into a rounding operation. I think that will work for all cases but you may want to test it (and keep an eye on it) just in case.

like image 98
paxdiablo Avatar answered Nov 14 '22 16:11

paxdiablo