4

Possible Duplicate:
strange output in comparision of float with float literal

#include<stdio.h>
int main()
{
float me = 1.7;
if(me==1.7)
   printf("C");
else
   printf("C++");
}

Output: C++

Now the reason for this behaviour is said that many floating point numbers cant be represented with absolute precision in binary.

My question is that - If computer thinks and manipulates in binary. Any uncertanity in representation of me would be same for 1.7 when compared. So both should be equal.

ALso how typecasting solves this problem? (float)1.7

Community
  • 1
  • 1
Shubham
  • 21,300
  • 18
  • 66
  • 89
  • 7
    [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.sun.com/source/806-3568/ncg_goldberg.html) – Amarghosh Aug 31 '10 at 09:39
  • 1
    duplicate of http://stackoverflow.com/questions/1839422/strange-output-in-comparision-of-float-with-float-literal – Jens Gustedt Aug 31 '10 at 09:46

7 Answers7

13

You are comparing a float to a double. the literal 1.7 is a double.

You've stored that in a float, which might have less precision than a double, thus the me == 1.7 is comparing 1.7 as a float(promoted to a double) to 1.7 as a double.

In this case, me == 1.7f should make them compare as equal, or changing me to a double double me = 1.7;

In the general case though, you'd want equality to be compared using an epsilon as @duffymo shows.

Also, Obligatory read.

nos
  • 223,662
  • 58
  • 417
  • 506
  • Ok. Hmm that answers well but is it a rule in C++/C that when being compared number will be automatically be promoted to double? – Shubham Aug 31 '10 at 09:48
  • @Shubham A plain decimal number is always double; you should add `f` to make it a float – Amarghosh Aug 31 '10 at 09:58
2

Here is some reading material What Every Computer Scientist Should Know About Floating-Point Arithmetic

RvdK
  • 19,580
  • 4
  • 64
  • 107
2

The closest representation of 1.7 is different for float and double, so casting to a float should usually result in the same number.

One of the main reasons you can't compare floating point numbers is that identities that work for real numbers and integers don't necessarily work for floating point because of rounding - i.e. (x+y)+z and x+(y+z) can often be different (note that writing them that way will often not change a compiler's behavior, but you can induce the order by doing something the compiler wont optimize around).

For instance, (100 - (100 - .0000000001)) != .00000000001 using IEEE-754 doubles, even though math says they should be equal. So the computation that should be producing .00000000001 will be slightly off. This is especially a problem with more complicated calculations, such as linear algebra, where the answer can be the result of thousands of additions and subtractions, each of which can add to floating point rounding error.

IEEE-754 floating point can be very tricky, if you don't really understand what's going on.

I recommend the excellent "What every Computer Scientist Should Know About Floating-Point Arithmetic": http://docs.sun.com/source/806-3568/ncg_goldberg.html

Joe
  • 227
  • 1
  • 2
  • It's unfortunate IMHO that in most languages, if one operand of a comparator operator is `double`, the other operator will often be silently converted to `double`; IMHO the only types which should be implicitly converted to `double` *in that context* are integer types whose values are all precisely representable as `double`. In most cases, `(float)someDouble == someFloat` is more meaningful than `someDouble == (double)someFloat`, but because having `someFloat == someDouble` yield that behavior would prevent `==` from defining an equivalence relation, that would be a bad compiler default. – supercat Aug 29 '13 at 19:50
  • On the other hand, the fact that `(float)someDouble == someFloat` is often more semantically meaningful suggests that performing the equality check as `someDouble == (double)someFloat` isn't really a good default either. IMHO, the proper thing to do would be to require that the programmer *explicitly* convert one operand to the type of the other; it would be surprising if f1==d1 and f1==d2, but d1!=d2. On the other hand, having f1==(float)d1 and f1==(float)d2 when d1!=d2 would not be surprising at all. – supercat Aug 29 '13 at 19:53
2

Assuming an IEEE-754 representation, the literals 1.7f and 1.7 stand for the following values:

1.7f == 1.7000000476837158203125
1.7  == 1.6999999999999999555910790149937383830547332763671875

Clearly, these are not the same value, and thus they compare as false.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
1

float me = 1.7f;

Mayosse
  • 696
  • 1
  • 7
  • 16
0

It is a problem of representation concerning numerical analysis, since you have a limited amount of bit to represent the number what is represented is not exactly equal to the number you meant, it is just a close approximation to the nearest number representable with the bit you have. Take a read here

rano
  • 5,616
  • 4
  • 40
  • 66
0

The 1.7 is converted automatically to double in the comparison. So you're comparing 1.7 with 1.7d, which probably differ by some (double) machine epsilons.

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197