4

Possible Duplicates:
Difference between float and double
strange output in comparision of float with float literal

I am using visual C++ 6.0 and in a program I am comparing float and double variables For example for this program

#include<stdio.h>
int main()  
{    
    float a = 0.7f;
    double b = 0.7; 
    printf("%d %d %d",a<b,a>b,a==b);
    return 0;
 }  

I am getting 1 0 0 as output

and for

#include<stdio.h>
int main()  
{    
    float a = 1.7f;
    double b = 1.7; 
    printf("%d %d %d",a<b,a>b,a==b);
    return 0;
 }  

I am getting 0 1 0 as output.

Please tell me why I am getting these weird output and is there any way to predict these outputs on the same processor. Also how comparison is done of two variables in C ?

Community
  • 1
  • 1
Chetan Sharma
  • 41
  • 1
  • 1
  • 2
  • 5
    You should never compare floating point values for equality - due to known precision and rounding issues, the results are unpredictable. And this is a duplicate of many posts - will look up one soon. – Péter Török Oct 21 '10 at 14:58
  • 5
    Dupe of hundreds of "Are floating point numbers broken?" questions... read those until you get **that floating point numbers are inherently inaccurate**. –  Oct 21 '10 at 14:58
  • Trying to compare doubles and floats will lead to pain, frustration, heartbreak, and possibly madness. – FrustratedWithFormsDesigner Oct 21 '10 at 15:02
  • 2
    @delnan: I wouldn't describe floating point numbers themselves as inherently inaccurate. I would describe the conversion from decimal values to binary floating point values as inherently lossy. – Jon Skeet Oct 21 '10 at 15:03
  • 1
    related http://stackoverflow.com/questions/2743718/when-is-aa-true/2743780#2743780 :) – N 1.1 Oct 21 '10 at 15:07
  • 1
    @Jon Skeet: Yes, there are a lot of numbers that can be represented with floats. Sadly, there's an infinite number of rationals, and while juggling floats, one is almost guaranteed to run into those (i.e. inaccuarcies). So one is better of treating floats as *always* inaccurate and consider 100% accurate results an exception :) –  Oct 21 '10 at 15:07
  • 1
    @delnan: Do you consider integers to be inaccurate too? After all, they can't represent all numbers. Divide 5 by 2 and you'll get 2 in integer arithmetic, not 2.5 - but no-one says that integers are inaccurate, they just understand the set of possible values. I believe that encouraging that level of understanding for binary floating point values is better than bandying the word "inaccurate" around without qualification. (Also out of interest: do you consider *decimal* floating point types such as System.Decimal in .NET to be "inaccurate"?) – Jon Skeet Oct 21 '10 at 15:11
  • @Jon Skeet: I agree that one should understand how floats work. Floats (including decimals) are not real numbers, just an approximation thereof - so when treating them as such, one should at least keep in mind what this means in practice: inaccuracies (decimals are inaccurate, too - but use the base humans are used to, so the inaccuracies aren't that unexpected - 1/3 can't be represented in finited digits in base 10, "but that's okay, we'll round as always"). –  Oct 21 '10 at 15:48
  • @delnan: I disagree. I view floats and decimals as having exact values, which may only be approximations to the exact results of the computations which gave rise to them. 1.5 is exactly 1.5, just like 1 is exactly 1. Just because 6/5 isn't exactly 1 doesn't make the number 1 any less exact. Again, do you believe that integers aren't real numbers, just approximations? – Jon Skeet Oct 21 '10 at 16:21
  • @Jon Skeet: Yes, 1.5 is exactly 1.5 and 123.4567891213e-50 is exactly 123.4567891213e-50. But the latter might be the result of a computation that, in "real math", has a slightly different result, because the actual result can't be represented in this float format. Ints are accurate - by definition, they stay inside integer land and can represent every integer within their range (floats OTOH are in real number land, but they can't represent every real number). But perhaps we should now stop keeping this question alive :) –  Oct 21 '10 at 16:58
  • @delnan: But the result of a computation involving ints might be inaccurate too when expressed as an integer (5/2 as an example). I agree that integers can cover every value in their range, but I don't see that as a valid distinction between "accurate" and "inaccurate". I dare say you could come up with a precise definition along those lines, but *without* that definition, I believe that claiming floating point numbers are "inaccurate" is too vague to be particularly useful. Any specific floating point value is an exact and accurate representation of a real number (continued) – Jon Skeet Oct 21 '10 at 17:12
  • That real number can be easily determined. Yes, there are an infinite number of other real numbers which would be rounded to the same floating point value - but that's why I consider the *operations* (conversions etc) to be inaccurate - or at least "lossy" - rather than the values themselves being inaccurate. – Jon Skeet Oct 21 '10 at 17:14

4 Answers4

8

It has to do with the way the internal representation of floats and doubles are in the computer. Computers store numbers in binary which is base 2. Base 10 numbers when stored in binary may have repeating digits and the "exact" value stored in the computer is not the same.

When you compare floats, it's common to use an epsilon to denote a small change in values. For example:

float epsilon = 0.000000001;
float a = 0.7;
double b = 0.7;

if (abs(a - b) < epsilon)
  // they are close enough to be equal.
Starkey
  • 9,673
  • 6
  • 31
  • 51
2

1.7d and 1.7f are very likely to be different values: one is the closest you can get to the absolute value 1.7 in a double representation, and one is the closest you can get to the absolute value 1.7 in a float representation.

To put it into simpler-to-understand terms, imagine that you had two types, shortDecimal and longDecimal. shortDecimal is a decimal value with 3 significant digits. longDecimal is a decimal value with 5 significant digits. Now imagine you had some way of representing pi in a program, and assigning the value to shortDecimal and longDecimal variables. The short value would be 3.14, and the long value would be 3.1416. The two values aren't the same, even though they're both the closest representable value to pi in their respective types.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @Hans: The question changed after posting. It was *originally* printing `a` and `b` (nearly; actually `ab` which I assumed was a typo for `a,b`; it turns out it was just unformatted code, which made everything unclear). Will edit. – Jon Skeet Oct 21 '10 at 15:03
  • @Shynthriir: Look at the question pre-edit... – Jon Skeet Oct 21 '10 at 15:04
  • 1
    Apologies, I knew there had to be a reason. – Anthony Oct 21 '10 at 15:09
1

1.7 is decimal. In binary, it has non-finite representation.

Therefore, 1.7 and 1.7f differ.

Heuristic proof: when you shift bits to the left (ie multiply by 2) it will in the end be an integer if ever the binary representation is “finite”.

But in decimal, multiply 1.7 by 2, and again: you will only obtain non-integers (decimal part will cycle between .4, .8, .6 and .2). Therefore 1.7 is not a sum of powers of 2.

Benoit
  • 76,634
  • 23
  • 210
  • 236
0

You can't compare floating point variables for equality. The reason is that decimal fractions are represented as binary ones, that means loss of precision.

Andrey
  • 59,039
  • 12
  • 119
  • 163