I cant understand this program [duplicate] - c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
strange output in comparision of float with float literal
I can't understand this code. How can two same numbers be compared?
#include<stdio.h>
int main()
{
float a=0.8;
if(0.8>a) //how can we compare same numbers?
printf("c");
else
printf("c++");
return 0;
}
How can this problem be solved?

I do not understand why you ask whether the same two numbers can be compared. Why would you not expect a comparison such as 3 > 3 to work, even though 3 is the same as 3? The > operator returns true if the left side is greater than the right side, and it returns false otherwise. In this case, .8 is not greater than a, so the result is false.
Other people seem to have assumed that you are asking about some floating-point rounding issue. However, even with exact mathematics, .8 > .8 is false, and that is the result you get with the code you showed; the else branch is taken. So there is no unexpected behavior here to explain.
What is your real question?
In case you are asking about floating-point effects, some information is below.
In C source, the text “.8” stands for one of the numbers that is representable in double-precision that is nearest .8. (A good implementation uses the nearest number, but the C standard allows some slack.) In the most common floating-point format, the nearest double-precision value to .8 is (as a hexadecimal floating-point numeral) 0x1.999999999999ap-1, which is (in decimal) 0.8000000000000000444089209850062616169452667236328125.
The reason for this is that binary floating-point represents numbers only with bits that stand for powers of two. (Which powers of two depends on the exponent of the floating-point value, but, regardless of the exponent, every bit in the fraction portion represents some power of two, such as .5, .25, .125, .0625, and so on.) Since .8 is not an exact multiple of any power of two, then, when the available bits in the fraction portion are all used, the resulting value is only close to .8; it is not exact.
The initialization float a = .8; converts the double-precision value to single-precision, so that it can be assigned to a. In single-precision, the representable number closest to .8 is 0x1.99999ap-1 (in decimal, 0.800000011920928955078125).
Thus, when you compare “.8” to a, you find that .8 > a is false.
For some other values, such as .7, the nearest representable numbers work out differently, and the relational operator returns true. For example, .7 > .7f is true. (The text “.7f” in source code stands for a single-precision floating-point value near .7.)

0.8 is a double. When a is set to it, then it's converted into a float and at this point looses precision. The comparison takes the float and promotes it back to a double, so the value is for sure different.
EDIT: I can prove my point. I just compile and ran a program
float a = 0.8;
int b = a == 0.8 ? 1 : 0;
int c = a < 0.8 ? 1 : 0;
int d = a > 0.8 ? 1 : 0;
printf("b=%d, c=%d, d=%d, a=%.12f 0.8=%.12f \n", b, c, d, a, 0.8);
b=0, c=0, d=1, a=0.800000011921 0.8=0.800000000000
Notice how a now has some very small factional part, due to the promotion to double

Related

Float point numbers are not equal, despite being the same? [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Identical float values comparing as inequal [duplicate]
(4 answers)
Closed 3 years ago.
The program below outputs This No. is not same. Why does it do this when both numbers are the same?
void main() {
float f = 2.7;
if(f == 2.7) {
printf("This No. is same");
} else {
printf("This No. is not same");
}
}
Why does it do this when both numbers are the same?
The numbers are not the same value.
double can represent exactly typically about 264 different values.
float can represent exactly typically about 232 different values.
2.7 is not one of the values - some approximations are made given the binary nature of floating-point encoding versus the decimal text 2.7
The compiler converts 2.7 to the nearest representable double or
2.70000000000000017763568394002504646778106689453125
given the typical binary64 representation of double.
The next best double is
2.699999999999999733546474089962430298328399658203125.
Knowing the exact value beyond 17 significant digits has reduced usefulness.
When the value is assigned to a float, it becomes the nearest representable float or
2.7000000476837158203125.
2.70000000000000017763568394002504646778106689453125 does not equal 2.7000000476837158203125.
Should a compiler use a float/double which represents 2.7 exactly like with decimal32/decimal64, code would work as OP expected. double representation using an underlying decimal format is rare. Far more often the underlying double representation is base 2 and these conversion artifacts need to be considered when programming.
Had the code been float f = 2.5;, the float and double value, using a binary or decimal underlying format, would have made if (f == 2.5) true. The same value as a high precision double is representable exactly as a low precision float.
(Assuming binary32/binary64 floating point)
double has 53 bits of significance and float has 24. The key is that if the number as a double has its least significant (53-24) bits set to 0, when converted to float, it will have the same numeric value as a float or double. Numbers like 1, 2.5 and 2.7000000476837158203125 fulfill that. (range, sub-normal, and NaN issues ignored here.)
This is a reason why exact floating point comparisons are typically only done in select situations.
Check this program:
#include<stdio.h>
int main()
{
float x = 0.1;
printf("%zu %zu %zu\n", sizeof(x), sizeof(0.1), sizeof(0.1f));
return 0;
}
Output is 4 8 4.
The values used in an expression are considered as double (double precision floating point format) unless a f is specified at the end. So the expression “x==0.1″ has a double on right side and float which are stored in a single precision floating point format on left side.
In such situations float is promoted to double .
The double precision format uses uses more bits for precision than single precision format.
In your case add 2.7f to get expected result.
The literal 2.7 in f == 2.7 is converted to double that's why 2.7 is not equal to f.

How IF() function works while comparing float numbers? [duplicate]

This question already has answers here:
Floating point inaccuracy examples
(7 answers)
Closed 8 years ago.
int main()
{
float a = 0.7;
float b = 0.5;
if (a < 0.7)
{
if (b < 0.5) printf("2 are right");
else printf("1 is right");
}
else printf("0 are right");
}
I would have expected the output of this code to be 0 are right.
But to my dismay the output is 1 is right why?
int main()
{
float a = 0.7, b = 0.5; // These are FLOATS
if(a < .7) // This is a DOUBLE
{
if(b < .5) // This is a DOUBLE
printf("2 are right");
else
printf("1 is right");
}
else
printf("0 are right");
}
Floats get promoted to doubles during comparison, and since floats are less precise than doubles, 0.7 as float is not the same as 0.7 as double. In this case, 0.7 as float becomes inferior to 0.7 as double when it gets promoted. And as Christian said, 0.5 being a power of 2 is always represented exactly, so the test works as expected: 0.5 < 0.5 is false.
So either:
Change float to double, or:
Change .7 and .5 to .7f and .5f,
and you will get the expected behavior.
The issue is that the constants you are comparing to are double not float. Also, changing your constants to something that is representable easily such as a factor of 5 will make it say 0 is right. For example,
main()
{
float a=0.25,b=0.5;
if(a<.25)
{
if(b<.5)
printf("2 are right");
else
printf("1 is right");
}
else
printf("0 are right");
}
Output:
0 are right
This SO question on Most Effective Way for float and double comparison covers this topic.
Also, this article at cygnus on floating point number comparison gives us some tips:
The IEEE float and double formats were designed so that the numbers
are “lexicographically ordered”, which – in the words of IEEE
architect William Kahan means “if two floating-point numbers in the
same format are ordered ( say x < y ), then they are ordered the same
way when their bits are reinterpreted as Sign-Magnitude integers.”
This means that if we take two floats in memory, interpret their bit
pattern as integers, and compare them, we can tell which is larger,
without doing a floating point comparison. In the C/C++ language this
comparison looks like this:
if (*(int*)&f1 < *(int*)&f2)
This charming syntax means take the address of f1, treat it as an
integer pointer, and dereference it. All those pointer operations look
expensive, but they basically all cancel out and just mean ‘treat f1
as an integer’. Since we apply the same syntax to f2 the whole line
means ‘compare f1 and f2, using their in-memory representations
interpreted as integers instead of floats’.
It's due to rounding issues while converting from float to double
Generally comparing equality with floats is a dangerous business (which is effectively what you're doing as you're comparing right on the boundary of > ), remember that in decimal certain fractions (like 1/3) cannot be expressed exactly, the same can be said of binary,
0.5= 0.1, will be the same in float or double.
0.7=0.10110011001100 etc forever, 0.7 cannot be exactly represented in binary, you get rounding errors and may be (very very slightly) different between float and double
Note that going between floats and doubles you cut off a different number of decimal places, hence your inconsistant results.
Also, btw, you have an error in your logic of 0 are right. You don't check b when you output 0 are right. But the whole thing is a little mysterious in what you are really trying to accomplish. Floating point comparisons between floats and doubles will have variations, minute, so you should compare with a delta 'acceptable' variation for your situation. I've always done this via inline functions that just perform the work (did it once with a macro, but thats too messy). Anyhow, yah, rounding issues abound with this type of example. Read the floating point stuff, and know that .7 is different than .7f and assigning .7 to a float will cast a double into a float, thus changing the exact nature of the value. But, the programming assumption about b being wrong since you checked a blared out to me, and I had to note that :)

C : Strange error when using float and double [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
strange output in comparision of float with float literal
Comparison of float and double variables
I have a test with double and float in C, but I cannot explain why.
float x = 3.4F;
if(x==3.4)
printf("true\n");
else printf("false\n");
double y = 3.4;
if (y==3.4)
printf("true\n");
else printf("false\n");
The result will be False and True. Please explain for me please.
3.4 cannot be exactly represented as a double for the same reason that one third cannot be exactly represented as a base-10 decimal number using a finite number of digits -- the representation recurs.
So, the double literal 3.4 is actually the double value closest to 3.4. 3.4F is the float value closest to 3.4, but that's different from the closest double value.
When you compare a float with a double, the float is converted to double, which doesn't change its value.
Hence, 3.4F != 3.4, just as 0.3333 != 0.33333333
x == 3.4 should be x == 3.4F, otherwise the 3.4 is a double (by default). Always compare like with like, not apples and oranges.
Edit:
Whether the result of the comparison between types of different precision is true or false depends on the floating point representation of the compiler.
Floating point numbers, whether single precision (float) or double, are an approximation.
No guarantee that the result will be false and true, but the basic idea is pretty simple: 3.4 has type double. When you assign it to a float, it'll get rounded. When you compare, that rounded number will be promoted back to a double, not necessarily the same double as 3.4.
In the second case, everything's double throughout.
Comparing for equality
Floating point math is not exact. Simple values like 0.2 cannot be precisely represented using binary floating point numbers, and the limited precision of floating point numbers means that slight changes in the order of operations can change the result. Different compilers and CPU architectures store temporary results at different precisions, so results will differ depending on the details of your environment. If you do a calculation and then compare the results against some expected value it is highly unlikely that you will get exactly the result you intended.
In other words, if you do a calculation and then do this comparison:
if (result == expectedResult)
then it is unlikely that the comparison will be true. If the comparison is true then it is probably unstable – tiny changes in the input values, compiler, or CPU may change the result and make the comparison be false.
As a tip, comparing floating point numbers (float or double) with '==' is in most cases a bad programming practice, as you might never get the statement to be true. The two numbers might differ in their least significant bits.
It is better using something like:
abs(x - y) < EQUALITY_MARGIN
With EQUALITY_MARGIN being an adequately small number.

Can anyone explain me this feature simply?

I have the following code,
float a = 0.7;
if(0.7 > a)
printf("Hi\n");
else
printf("Hello\n"); //Line1
and
float a = 0.98;
if(0.98 > a)
printf("Hi\n");
else
printf("Hello\n"); //Line2
here line1 outputs Hi but Line2 outputs Hello. I assume there would be a certain criteria about double constant and float, i.e any one of them would become larger on evaluation. But this two codes clarify me that situation can be come when double constant get larger and some other times float get larger. Is there any rounding off issue behind this? If it is, please explain me. I am badly in need of this clear..
thanks advance
What you have is called representation error.
To see what is going on you might find it easier to first consider the decimal representations of 1/3, 1/2 and 2/3 stored with different precision (3 decimal places or 6 decimal places):
a = 0.333
b = 0.333333
a < b
a = 0.500
b = 0.500000
a == b
a = 0.667
b = 0.666667
a > b
Increasing the precision can make the number slightly larger, slightly smaller, or have the same value.
The same logic applies to binary floating point numbers.
float a = 0.7;
Now a is the closest single-precision floating point value to 0.7. For the comparison 0.7 > a that is promoted to double, since the type of the constant 0.7 is double, and its value is the closest double-precision floating point value to 0.7. These two values are different, since 0.7 isn't exactly representable, so one value is larger than the other.
The same applies to 0.98. Sometimes, the closest single-precision value is larger than the decimal fraction and the closest double-precision number smaller, sometimes the other way round.
This is part of What Every Computer Scientist Should Know About Floating-Point Arithmetic.
This is simply one of the issues with floating point precision.
While there are an infinite number of floating point numbers, there are not an infinite number of floating point representations due to the bit-constraints. So there will be rounding errors when using floats in this manner.
There is no criteria for where it decides to round up or down, that would probably be language -implementation or compiler dependent.
See here: http://en.wikipedia.org/wiki/Floating_point, and http://en.wikipedia.org/wiki/IEEE_754 for more details.

Comparison of float and double variables [duplicate]

This question already has answers here:
Closed 12 years ago.
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 ?
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.
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.
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.
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.

Resources