#include<stdio.h>
#include<conio.h>

int main()
{
    float a=0.7;
    if(a<0.7)
    printf("C");
    else
    printf("C++");
    getch();
    return 0;
}

The above code prints 'C'.
Whereas the following two codes prints 'C++'. Why is that?

#include<stdio.h>
#include<conio.h>

int main()
{
    float a=0.7;
    if(a>0.7)
    printf("C");
    else
    printf("C++");
    getch();
    return 0;
}
#include<stdio.h>
#include<conio.h>

int main()
{
    float a=0.7;
    if(a<0.7f)
    printf("C");
    else
    printf("C++");
    getch();
    return 0;
}

Recommended Answers

All 10 Replies

Your first code prints c++ for me using VC++ 2008 Express. What compiler are you using?

Stricktly speaking it's possible and valid behaviour of floating-point calculations.
Floating point types are not mathematical real numbers. The last ones have "infinit" precision but doubles and floats are approximations of real numbers.

So C language literal 0.7 is an approximation (of double type by definition) of the real number 0.7 and 0.7f is ANOTHER approximation of this number. May be 0.7 == 0.7f, may be 0.7 != 0.7f!

Moreover, don't intend that the following code prints OK:

double x = 7.0 / 10.0;
if (x == 0.7)
   printf("OK\n");

You can read (by scanf) 0.7 from a text file but you can't intend that the number is equal to 0.7 literal from your code.
Look at your code fragment again:

float a=0.7;    
    if (a > 0.7)
      ...
    if (a < 0.7f)
      ...

The 1st if expression evaluation: promote a to double then compare with double type literal.
The 2nd: compare float a var value with float type literal.
Absolutely different operations involved...

Moral:
1. The only "trustworthy" equality tests for floating-point data are == 0.0 and != 0.0.
2. Remember that double and float values are approximations, not exact values.
3. Never use float type in math calculations: it has too low precision.

Probably it was your maiden filght over Computational Mathematics Area ;).
Bon voyage!...

Some addition.
In real world floating-point arithmetics (float, double and long double types in C) based on a binary representation of scaled numbers (as usually it's a binary fraction multiplied to power of 16). So you can't represent 0.7 decimal fraction as a binary fraction exactly: remember that fact.

For simplicity and clarification suppose we have CPU with decimal arithmetics. You are C compiler designer and you want to implement floating-point if expression code generator.

float xf = 1.0/3.0; /* you have 0.3333333*10^0 in xf */
double xd = 1.0/3.0; /* you have 0.3333333333333333*10^0 in xd */
/* Approximations of 10^0*0.333333..... */
if (xf < xd)
   ...

Well, the 1st op is type (precision) balancing: you must promote short value to correspondent longer type. Possible solutions:

0.3333333 => 0.333333300000000 /* fill by zeroes*/
0.3333333 => 0.333333350000000 /* add 5 in the next digital position */

You like the 1st solution: OK, now a program generated by your compiler returns true in this test. But your old fellow from AnotherCompiler, Ltd implemented the 2nd solution (why not?). Another compiler compares 0.33333335 with 0.3333333333333333 and returns false.

That's all. What's the best compiler?..

Thanks ArkM. Admittedly, that's a lot of things i don't understand yet. will try to figure it out though. :)

>What compiler are you using?

DEV-C++

0.3333333 => 0.333333300000000 /* fill by zeroes*/
0.3333333 => 0.333333350000000 /* add 5 in the next digital position *

What's the logic behind adding 5 after 0.3333333? Just filling it with zeroes seems more reasonable.

Pay attention: 0.33333335 is a better approximation of the periodical fraction 1/3 than 0.33333330...
Sometimes it's a very useful method to round off numbers.

Yes, but why 0.33333335? 0.33333334 seems like a much better approximation.

Also, i checked the outputs initialing 'a' to a few more numbers (from 0.1 - 0.9). I got the output a C++ for all except 0.7 and 0.9.

I apologize if the questions sound too 'noob'ish, i just haven't grasped the concept yet.

1. When we add a half of the next digit range (0.00000005) we do not know that it's 1/3 and 0.33333334 is a "better" approximation (if we know then we add 0.000000033333333, of course ;)). We add 0.00000005 to ALL numbers. Don't forget: it's only one of possible floating-point promotion solutions and we need special studies to prove its (dis)advanatages. In practice we all use builtin float to double promotions.

2. Well, try ALL float fractions (~10000000) and you will find yet another cases ;). Or better try all double fractions (~10000000000000000)...

I hope today you know why it was a buzzing under engine cowling...

Oh ok. i think i understand it now.

>Or better yet try all double fractions
Yeah. . . i think i'll pass on that. :P

Thanks a lot, dude!

use
if(a<=0.7)
printf("c");
else
printf("c++");

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.