1

I have already asked this question, but the answer to this specific subpart is not clear to me. See the code below:

float f=2.5;
if (f==2.5)
printf("abc");
else
printf("xyz"); //prints abc

I know that if we had taken 2.2 instead of 2.5, it would output the opposite as float is taken as double and floating point nos. Shouldn't they be equated actually? I want to know why there is an exception with the numbers having their last decimal digit 5.

Marievi
  • 4,951
  • 1
  • 16
  • 33
Deya
  • 47
  • 3

4 Answers4

5

Because it can be expressed as an integer times an integral power of 2. E.g. 2.5 = 5/2 = 5×(2-1). This matches directly the common representation of a floating point value.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • Times an *integral* power of 2. Just sayin' ;-) – Bathsheba Feb 07 '17 at 09:11
  • Every real number can be expressed that way. it is only a matter of bits - sometimes an infinite number ... – too honest for this site Feb 07 '17 at 10:04
  • @Olaf: rational numbers, strictly. – Bathsheba Feb 07 '17 at 10:18
  • @Olaf: And not even all rational numbers; 1/3 simply cannot be represented that way. – MSalters Feb 07 '17 at 10:43
  • @MSalters: Notice the last part of my comment. Which is the actual crux. – too honest for this site Feb 07 '17 at 10:46
  • @Bathsheba: Notice the last part of my comment. Which is the actual crux – too honest for this site Feb 07 '17 at 10:46
  • @MSalters: You *almost* can, see the standard way of proving Urysohn's lemma. – Bathsheba Feb 07 '17 at 10:48
  • @Olaf: That sadly will never apply to irrationals. – Bathsheba Feb 07 '17 at 10:48
  • @Bathsheba: I might miss something, but isn't their point that they require an infinite number of digits for their representation? So if you **had** an infinite number of digits, what would be the problem? – too honest for this site Feb 07 '17 at 10:50
  • The central tenet is that an irrational number cannot be written as a / b, no matter how big a and b are. – Bathsheba Feb 07 '17 at 10:56
  • @Bathsheba: Yes, I know that. It also reqires `a` and `b` being integers. But I never required that. Maybe I should emphasize that I indeed mean _infinite_, not "a very large number of". Apparently this is not possible. – too honest for this site Feb 07 '17 at 10:59
  • @Olaf: Obviously, we're talking about integers. Any real number `x` can be written as `a/b` if you drop that condition, that's trivial : `a=x, b=1`. As for "an infinite number of digits", note that the set of integers is already unbounded. There's no finite upper bound, and therefore no finite number of digits either. – MSalters Feb 07 '17 at 11:07
  • @MSalters: "Any real number x can be written as a/b" - You mean "rationale number". Real numbers include those which can't be as pointed out by bathsheba. That's why I added this clarification. But you missed the actual point of my comment, which is exactly the reason for OPs problem. – too honest for this site Feb 07 '17 at 11:27
  • @Olaf: No, i precisely mean what I wrote. Any real number `x` can be written as `a/b` if and only if you drop the condition that `a` and `b` are integers. But that's trivial, so a∈ℕ is implied. – MSalters Feb 07 '17 at 11:34
  • @MSalters: Not clear why you criticize my addition about the integers. Please read the thread carefully again. – too honest for this site Feb 07 '17 at 11:43
  • "can be expressed as an integer times a power of 2" has its limitations. `1 + pow(2,-25)` an be represented exactly as decimal text and "as an integer times a power of 2", yet will not compare equally due to finite precision of binary floating point - still a good observation. – chux - Reinstate Monica Feb 07 '17 at 14:05
  • @chux: I believe ordinary 64-bits IEEE 754, as is commonly used for the default floating point type `double` in C++, has around 52 bits for the mantissa. – Cheers and hth. - Alf Feb 07 '17 at 14:11
  • @Bathsheba: Thanks, fixed the wording. :) – Cheers and hth. - Alf Feb 07 '17 at 14:18
  • Have an upvote! – Bathsheba Feb 07 '17 at 14:19
  • @Cheersandhth.-Alf [binary64](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) has 53 bits of numerical significance (52 explicitly coded). The issue of my comment applies with the narrower `float f=...;` with its 24 bits of significance and how `1 + pow(2,-25)` would not store exactly as `float` even though it meets this answer criteria. – chux - Reinstate Monica Feb 07 '17 at 14:59
  • @chux: Feel free to amend the answer, please. I chose to not discuss limits of representation because the OP is struggling with a much more fundamental issue. But I think he/she got the idea by now. :) – Cheers and hth. - Alf Feb 07 '17 at 15:27
5

2.5 can be written as a dyadic rational, and given that it is also of sufficiently small magnitude, it can be represented exactly in IEEE754 floating point. 2.25 can also be represented perfectly too, for example. Reference: https://en.wikipedia.org/wiki/Dyadic_rational


floating point nos. shouldnt be equated actually

This is little more than a rule of thumb. And arbitrary comparision using badly thought out tolerances can be harmful. There is nothing mysterious about floating point. It's only that most of them cannot be represented as decimals (which is what developers tend to think in), that's all.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • You probably meant times instead of plus, and I think it wouldn't hurt to use common speech “power of two” or “binary fraction” rather than the math-ish “dyadic rational”. – Cheers and hth. - Alf Feb 07 '17 at 08:55
  • @Cheersandhth.-Alf: I was attempting to think of this as a "proper fraction". There's no real need for that, so I've removed it. – Bathsheba Feb 07 '17 at 09:02
  • Good ref to _dyadic rational_. Also need "... of sufficiently small magnitude _and limited precision_" - same reason as in this [comment](http://stackoverflow.com/questions/42085272/why-does-the-float-having-5-as-its-last-decimal-digit-give-the-correct-output-in/42085325?noredirect=1#comment71356312_42085325) – chux - Reinstate Monica Feb 07 '17 at 15:22
0

If you measure a distance, how many millimeters is it? And is it not a tiny bit more or a tiny bit less? And if you zoom in on your yardstick, how many micrometers is it? And not a bit more or a bit less?

This to illustrate that floating point uses bits to represent an approximation of a value and cannot (cannot always) represent the exact value.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
0

The number 2.5 passes the test because 0.5 has an exact representation as a binary fraction. It is 2-1. In fact, every negative power of 2 has 5 as its last digit. Here are a few examples

2^-1  = 0.5000000000000000
2^-2  = 0.2500000000000000
2^-3  = 0.1250000000000000
2^-4  = 0.0625000000000000
2^-5  = 0.0312500000000000
2^-6  = 0.0156250000000000
2^-7  = 0.0078125000000000
2^-8  = 0.0039062500000000
2^-9  = 0.0019531250000000
2^-10 = 0.0009765625000000
2^-11 = 0.0004882812500000

Things to note:

  1. Most implementations of the C language express floating point numbers as the sum of negative powers of 2 (the sum itself is then multiplied by a power of 2).
  2. The pattern you see above will continue for all negative powers of 2 . That's because when the 50 at the end is divided by 2, it's always going to yield a number with a 5 at the end, and that 5 will be one more decimal place to the right.
  3. When you sum any combination of the negative powers of 2, the smallest number will always contribute the 5 at the end of the number, and that 5 will not be summed with a non-zero digit from any of the larger numbers.

So all numbers with an exact representation end with 5. However, that's not to say that every number that ends in 5 has an exact representation. For example 0.385 does not have an exact representation, and will fail the equality test.

user3386109
  • 34,287
  • 7
  • 49
  • 68