19

Given the C code:

#include <math.h>  
#include <stdio.h>  
int main(){  
 int i;  
 double f=log(2.0)/log(pow(2.0,1.0/2.0));  
 printf("double=%f\n",f);  
 printf("int=%d\n",(int) f);  
}

I get the output:

double=2.000000
int=1

f is apparently at least 2.0. Why is the cast value not 2?

  • 11
    It seems like the premise of the question is false, from the answers. The real "problem" is that printf rounds floating point numbers. –  Apr 27 '16 at 03:41
  • You might also consider a case where int has the same size as double and you do something like `log((double)int_64_variable)`. I am more inclined doing this on a piece of paper than writing a c program for this. ;) – sjsam Apr 27 '16 at 04:05
  • 1
    Also note that casting to `int` does *not* floor but rather truncates toward zero. This matters for negative values. – jamesdlin Apr 27 '16 at 04:15
  • 1
    Title of the question should really be "why does `printf` round this particular double like this?"... – hyde Apr 27 '16 at 13:43

3 Answers3

33

Because the value of the double was less than 2

double=1.99999999999999978
int=1

Try it but this time add some precision

#include <math.h>  
#include <stdio.h>  
int main(){  
 int i;  
 double f=log(2.0)/log(pow(2.0,1.0/2.0));  
 printf("double=%0.17f\n",f);  
 printf("int=%d\n",(int) f);  
}

Confusing as hell the first time you experience it. Now, if you try this

#include <math.h>  
#include <stdio.h>  
int main(){  
 int i;  
 double f=log(2.0)/log(pow(2.0,1.0/2.0));  
 printf("double=%0.17f\n",f);  
 printf("int=%d\n",(int) f);  
 printf("int=%d\n", (int)round(f));
}

It will correctly round the value. If you look in the man page (on a mac at least) you'll see the following comment...

round, lround, llround -- round to integral value, regardless of rounding direction

What do they mean by direction, it's all specified in IEEE 754. If you check the different ways to round to an integer... floor is mentioned as rounding towards -ve infinity which is in this case was towards 1 :)

Harry
  • 11,298
  • 1
  • 29
  • 43
7

Integer does not take a rounded up value but makes a truncation. So, if f is equal to 1.999999999999[..]9, the int value will be 1.

Also, as the double wants to be the more accurate possible, he will take a rounded up value considering the number of characters he can show, which is 2.000000.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Thomas
  • 337
  • 2
  • 8
7

Floating point types are unable to represent some numbers exactly. Even though mathematically, the calculation should be exactly 2, with IEEE754 floating points, the result turns out to be slightly less than 2. For more information see this question.

If you increase the precision of your output by specifying %.20f instead of just %f, you will see that the number is not exactly 2, and that when printing with less accuracy, the result is simply rounded.

When converting to an int however, the full accuracy of the floating point type is used, and since it comes to just under 2, the result when converting to an integer is 1.

Community
  • 1
  • 1
dreamlax
  • 93,976
  • 29
  • 161
  • 209