954,500 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Problem with floats

#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;
}
devnar
Junior Poster
149 posts since Sep 2008
Reputation Points: 124
Solved Threads: 18
 

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

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

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!...

ArkM
Postaholic
2,001 posts since Jul 2008
Reputation Points: 1,234
Solved Threads: 348
 

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?..

ArkM
Postaholic
2,001 posts since Jul 2008
Reputation Points: 1,234
Solved Threads: 348
 

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++

devnar
Junior Poster
149 posts since Sep 2008
Reputation Points: 124
Solved Threads: 18
 
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.

devnar
Junior Poster
149 posts since Sep 2008
Reputation Points: 124
Solved Threads: 18
 

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.

ArkM
Postaholic
2,001 posts since Jul 2008
Reputation Points: 1,234
Solved Threads: 348
 

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.

devnar
Junior Poster
149 posts since Sep 2008
Reputation Points: 124
Solved Threads: 18
 

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...

ArkM
Postaholic
2,001 posts since Jul 2008
Reputation Points: 1,234
Solved Threads: 348
 

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!

devnar
Junior Poster
149 posts since Sep 2008
Reputation Points: 124
Solved Threads: 18
 

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

smart_pc
Newbie Poster
13 posts since Sep 2008
Reputation Points: 10
Solved Threads: 2
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You