4

With the following code,

#include <stdio.h>

int main(void){
  float x;
  x=(float)3.3==3.3;
  printf("%f",x);
  return 0;
}

the output is 0.00000

but when the number 3.3 is replaced with 3.5,

#include <stdio.h>

int main(void){
  float x;
  x=(float)3.5==3.5;
  printf("%f",x);
  return 0;
}

the output is 1.0000

Why is there a difference in output?

Jens
  • 69,818
  • 15
  • 125
  • 179
  • 3
    Why would you store the boolean result of an equality operation as a floating point number? – Some programmer dude Aug 09 '13 at 07:59
  • 4
    Also, you might want to read [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). – Some programmer dude Aug 09 '13 at 07:59
  • And thirdly, learn the difference between `float` and `double`, both generally and when it comes to literals. – Some programmer dude Aug 09 '13 at 08:00
  • 3
    You may like this post: http://blog.frama-c.com/index.php?post/2011/11/08/Floating-point-quiz – Pascal Cuoq Aug 09 '13 at 08:08
  • Maybe you want to compare two float: fabs(x1-x2) < 1e-8 – kaitian521 Aug 09 '13 at 08:20
  • I prefer the article **[What Every Programmer Should Know About Floating-Point Arithmetic](http://floating-point-gui.de/)** – abelenky Aug 09 '13 at 14:32
  • 1
    I second @JoachimPileborg recommend of the Goldberg article (also available in [PDF](http://www.validlab.com/goldberg/paper.pdf) ), and will recommend an blog entry ["Comparing Floating Point Numbers, 2012 Edition"](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/) by Bruce Dawson. – mctylr Aug 09 '13 at 19:34

5 Answers5

10

You should understand that in C the literal 3.3 has type double. Converting a double to a float may lose precision, so the comparison of 3.3F with 3.3 yields false. For 3.5 the conversion is lossless since both can be represented exactly and the comparison yields true.

It's somewhat related to (in base 10 instead of base 2) comparing

3.3333333 with 3.3333333333333333  (false)
3.5000000 with 3.5000000000000000  (true)
Jens
  • 69,818
  • 15
  • 125
  • 179
  • 1
    The other part of knowing what's going on is that the `(float)3.3` value is promoted back to `double` before the comparison. – caf Aug 09 '13 at 08:10
  • @caf: It is good to know that, but it is not relevant to this question. As long as `==` returns true if and only if the left operand equals the right operand, it does not matter whether it promotes one of the operands or implements some sort of direct comparison. `(float) 3.3 == 3.3` would return the same result either way. – Eric Postpischil Aug 09 '13 at 13:41
5

Due to rounding errors, most floating-point numbers end up being slightly imprecise. As long as this imprecision stays small, it can usually be ignored. However, it also means that numbers expected to be equal (e.g. when calculating the same result through different correct methods) often differ slightly, and a simple equality test fails.

And in your case, converting a double to float loses some precision.

You have to be very careful when you compare floating-points.

I suggest you to take a look at this link: What is the most effective way for float and double comparison?

This article may help you to understand why it appends : http://www.cprogramming.com/tutorial/floating_point/understanding_floating_point_representation.html


A little explanation about floating-point numbers and why this is happening :

Floating-point numbers are typically packed into a computer datum as the sign bit, the exponent field, and the significand (mantissa), from left to right.

Basically, you can say that a floating-point number is :

number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits)

Of course, depending on if you are using a float or a double, the precision is different :

          | Sign | Exponent | Significand | Total bits
float     | 1    | 8        | 23          | 32
Double    | 1    | 11       | 52          | 64

Here you can see why you may lose some data by converting a double to float.

In you case, it seems that the computer is able to compute 3.5 exactly, but not 3.3. Somehow, with the formula, we may assume that you are doing something like :

3.3333333 == 3.333333333333333   // is false because of the precision
3.5000000 == 3.500000000000000   // is true

// I tried to match the precision of the float in the left
// and the precision of the double on the right
Community
  • 1
  • 1
Pierre Fourgeaud
  • 14,290
  • 1
  • 38
  • 62
4

== performs an equality check. Equality checks are problematic with floats (see http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm)

So, once you get a false and once you get a true (1).

For a more robust way of comparing floats see - What is the most effective way for float and double comparison?

Community
  • 1
  • 1
Vadim
  • 2,847
  • 15
  • 18
  • Note: Bruce Dawson has updated his entry to reference to a blog entry (Comparing Floating Point Numbers, 2012 Edition)[https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/]. And the related SO Q&A is actually incomplete in its treatment of floating point comparison. (No single answer is comprehensive in identifying of even just the major issues). – mctylr Aug 09 '13 at 19:41
4

The difference is that 3.5 can be represented exactly as a binary floating point number, while 3.3 cannot.

Since the mathematical 3.3 cannot be exactly represented, 3.3, as a double precision number, is a better approximation than the single precision number (float)3.3, and therefore has a different value.

Joni
  • 108,737
  • 14
  • 143
  • 193
0

Why is there a difference in output?

A theoretical, but probably unsatisfying answer wearing a Math / CS () hat is:

  • Because floating point numbers are finite, and thus not equal to the R http://mathurl.com/mgwavz7 numbers we are use to in mathematics (and much of the real world).
  • Floating point numbers are binary as opposed to decimal, so some fractions that are finite in decimal representation, but are repeating or transcendental (like Pi http://mathurl.com/62kzla or the base of the natural logarithm e) in binary (or radix 2).

@Jens

mctylr
  • 5,159
  • 20
  • 32