-2

i have following code which gives strange output

#include<stdio.h>
void main()
{
 float a, x;
 a=6.7;
 if(a==6.7)
  printf("1\n");
 else
  printf("2\n");


 x=8.5;
 if(x==8.5)
  printf("1\n");
 else
  printf("2\n");

}

output

$ ./a.out 
2
1

if i suffix numbers with f e.g. "6.7f" in if condition then i get proper output, I don't get why is this strange behavior?

Christian Ternus
  • 8,406
  • 24
  • 39
twid
  • 6,368
  • 4
  • 32
  • 50
  • 6
    Floating point numbers are inherently imprecise, and should (almost) never be tested for equality. See http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – Robᵩ Oct 24 '13 at 20:57
  • 3
    People, please do **not** upvote this. Already discussed hundreds of times. –  Oct 24 '13 at 20:59
  • 1
    Related: http://blog.frama-c.com/index.php?post/2011/11/08/Floating-point-quiz – Pascal Cuoq Oct 24 '13 at 21:01

4 Answers4

5

float has less precision than double, which would be the default type used for floating point literals. Since 6.7 cannot be represented with a finite number of binary digits, the less precise float representation does not equal the double representation.

jxh
  • 69,070
  • 8
  • 110
  • 193
4

6.7 is a double, so when you say a=6.7 you're truncating a double to a float.

Because floating point numbers are stored in base 2, not base 10, it's impossible to represent 6.7 with complete precision. So when being truncated to a float, you lose a bit of information in this case. The same does not happen with 8.5, because 8.5 CAN be stored with complete precision in base 2.

Then, when you compare (a==6.7), you're comparing the different representations, which - as explained above - are not equal.

Taylor Brandstetter
  • 3,523
  • 15
  • 24
4

Unsuffixed floating point literals are of type double, not of type float.

6.7    /* double */
6.7f   /* float  */
ouah
  • 142,963
  • 15
  • 272
  • 331
3

Representation of floating point numbers in computers have limiting accuracy. You should never use simple == to compare two floating point numbers. Instead you can use

if(fabs(a-6.7) < epsilon) where epsilon is some small enough number but not smaller than the accuracy of the computer FP numbers representaiton (e.g. FP32 for float or FP64 for double).

Edit: As pointed out in the discussion below, never use should be rephrased to it is not advisable. See the discussion for the details, may be of use for people who use floating point often in their programs. Also the section Accuracy problems at this link may be important to keep in mind.

Igor Popov
  • 2,588
  • 17
  • 20
  • The sentence “You should never use simple == to compare two floating point numbers” is wrong. `==` should, as any other programming construct, be used when appropriate. Your advice on choosing an epsilon (assuming that is the correct solution) is very vague. The acronyms “FP32” and “FP64” do not exist in either the context of C or the context of IEEE 754. – Pascal Cuoq Oct 24 '13 at 22:19
  • @PascalCuoq No, you are wrong. I have been programming scientific software for 10 years and it is a basic knowledge that comparing FP numbers using `==` is very wrong. This is something which we first teach students. – Igor Popov Oct 25 '13 at 11:00
  • @PascalCuoq Of course one can use any construct given by a language but using `==` to compare FP numbers gives outcome that is not expected. In exact mathematical sense equality of real numbers is precise, while in programming it is not due to the limited accuracy of FP numbers as represented in the machines. Beginners usually use `==` for FP numbers instinctively, which is often cause for bugs that are difficult to notice. This is a reason to point the beginners to serious potential trouble when using `==` with FP. – Igor Popov Oct 25 '13 at 11:11
  • The quiz I linked to, http://blog.frama-c.com/index.php?post/2011/11/08/Floating-point-quiz , contains only questions that involve `==` between floating-point values. All answers are completely predictable assuming a standard-compliant C compiler providing access to IEEE 754-compliant floating-point. You are free to teach students what you want. I do not know enough about “scientific software” to tell whether it is always wrong to use `==` there. But the OP did not say he was programming scientific software and the answer to his question is not “Never use `==`”. – Pascal Cuoq Oct 25 '13 at 11:13
  • The answer to the question, as asked, is an explanation about C promotions and about the types of floating-point literals in C. – Pascal Cuoq Oct 25 '13 at 11:14
  • Thanks for the link!I agree with you that "never use" is maybe too strong,I should reword "it is not advisable". `==` is exact for IEEE 754 but outcome of `==` can be unexpected for many people, as OP's initial post indicates too. I mean atomistic quantum mechanical simulations of nanomaterials under "scientific software", which is my expertize. Such a software involves many FP arithmetics, so usage of `==` can be quite dangerous.Eg. in s.p.FP 0.1 is actually ~0.10000000149, which error can be larger than desired accuracy, so `if(fp1==fp2)` statement can wrongly branch due to 10^-9 mismatch. – Igor Popov Oct 25 '13 at 11:54
  • I am not very familiar with the difficulties involved in using floating-point for real applications. If you care about reproducible results of floating-point programs, you might like http://arxiv.org/abs/cs/0701192 . Monniaux's problem (and mine) is that we want to write static analyzers that predict exactly what programs with floating-point computations do, but you may find it interesting as someone who uses floating-point computations. (Note that the compiler situation has gotten better since that report). – Pascal Cuoq Oct 25 '13 at 11:58
  • Yes, I care about reproducibility of results, it is very important in sci. soft. and because of this reason we don't use `==`. I'll check the link, thanks. – Igor Popov Oct 25 '13 at 12:03