1

I was doing some question in C and I was asked to provide the output of this question :

#include <stdio.h>

int main()
{
    float a =0.7;
    if(a<0.7)
    {
        printf("Yes");
    }
    else{
        printf("No");
    }
}

By just looking at the problem I thought the answer would be NO but after running I found that it was YES I searched the web about float and found 0.30000000000000004.com

Just out of curiosity I ran the same code in python :

x = float(0.7)
if x < 0.7 : 
    print("YES")
else : 
    print("NO")

Here the output is NO

I am confused!
Maybe I am missing something
Please help me with this problem.

Thanks in advance!

JVApen
  • 11,008
  • 5
  • 31
  • 67
theshubhagrwl
  • 743
  • 9
  • 17
  • 1
    Looks like you have a double, convert it to float to than convert it back to double for the comparison. Loss of precision? Try 0.7f – JVApen Jun 16 '20 at 07:37
  • 1
    Floating point math is not exact. In C, you're comparing a `float` version of `0.7` to a `double` version of `0.7`. The `double` version is more accurate, and in this case the `float` version (which is converted to `double` for the comparison) happens to be smaller. In Python, `float` refers to a double-precision floating point number, so you're comparing a double `0.7` to another double `0.7`, and the result is that they're equal. – Tom Karzes Jun 16 '20 at 07:40
  • Didn't you ask a question regarding this yesterday? And someone pointed out that `a < 0.7` is a double but `a` is a float? Checked, nope, apparently you and another person had the same exact issue within 24h :) – Torxed Jun 16 '20 at 07:41
  • ....almost like two assignment dumps. – Martin James Jun 16 '20 at 10:30
  • theshubhagrwl, why did you code in C with `float` and not `double`? – chux - Reinstate Monica Jun 16 '20 at 14:54
  • The python code is not the same as the C code. – chux - Reinstate Monica Jun 16 '20 at 14:55
  • 1
    @chux-ReinstateMonica This question was asked in the quiz. I ran it at that time and later searched for the reason. – theshubhagrwl Jun 16 '20 at 17:21

2 Answers2

1
float a = 0.7;
if(a<0.7)

The first line above takes the double 0.7 and crams it into a float, which almost certainly has less precision (so you may lose information).

The second line upgrades the float a to a double (because you're comparing it with a double 0.7, and that's one of the things C does for you) but it's too late at that point, the information is already gone.

You can see this effect with:

#include <stdio.h>

int main(void) {
    float a = 0.7;
    float b = 0.7f;
    double c = 0.7;
    printf("a %.50g\nb %.50g\nc %.50g\n", a, b, c);
    return 0;
}

which generates something like:

a 0.699999988079071044921875
b 0.699999988079071044921875
c 0.69999999999999995559107901499373838305473327636719

Clearly, the double c variable has about double the precision (which is why they're often referred to as single and double precision) than both:

  • the double 0.7 crammed into the float a variable; and
  • the float b variable that had the float 0.7 stored into it.

Neither of them is exactly 0.7 due to the way floating point numbers work, but the double is closer to the desired value, hence not equal to the float.

It's like pouring a full four-litre bucket of water into a three-litre bucket and then back again. The litre you lost in the overflow of the smaller bucket doesn't magically re-appear :-)

If you change the type of your a to double, or use float literals like 0.7f, you'll find things work more as you expect, since there's no loss of precision in that case.


The reason why you don't see the same effect in Python is because there's one underlying type for these floating point values:

>>> x = float(.7)
>>> type(x)
<class 'float'>
>>> type(.7)
<class 'float'>

From the Python docs:

There are three distinct numeric types: integers, floating point numbers, and complex numbers. In addition, Booleans are a subtype of integers. Integers have unlimited precision. Floating point numbers are usually implemented using double in C.

Hence no loss of precision in that case.

The use of double seems to be confirmed by (slightly reformatted):

>>> import sys
>>> print(sys.float_info)
sys.float_info(
    max=1.7976931348623157e+308,
    max_exp=1024,
    max_10_exp=308,
    min=2.2250738585072014e-308,
    min_exp=-1021,
    min_10_exp=-307,
    dig=15,
    mant_dig=53,
    epsilon=2.220446049250313e-16,
    radix=2,
    rounds=1
)

The exponents and min/max values are identical to those found in IEEE754 double precision values.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
0

In a<0.7 the constant 0.7 is a double then a which is a float is promoted to double before the comparison.
Nothing guarantees that these two constants (as float and as double) are the same.

As float the fractional part of 0.7 is 00111111001100110011001100110011; as double the fractional part of 0.7 is 0110011001100110011001100110011001100110011001100110.
The value converted from float will have its mantissa filled with 0s when promoted to double.
Comparing these two sequences of bits shows that the double constant is greater than the float constant (the second bit already differs), which leads to displaying "Yes".

On the other hand, in python, only the double representation exists for floating point numbers; thus there is no difference between what is stored in a and the constant 0.7 of the comparison, which leads to displaying "No".

prog-fh
  • 13,492
  • 1
  • 15
  • 30