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

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.

Related

Unexpected behavior for floating point number in C programming [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
I'm getting confused with floating point number in c programming
#include <stdio.h>
int main()
{
float a = 255.167715;
printf("%f", a);
return 0;
} // it print value of 255.167709
Why it produce value like so? To be honest can you tell how it actually works in C programming?
In binary, 255.167715 is approximately 11111111.001010101110111101011110110010000000110001110…2. In your C implementation, most likely, the source code 255.167715 is converted to 11111111.0010101011101111010111101100100000001100011102, which is 255.16771499999998695784597657620906829833984375, because 255.167715 is a double constant, and that is the closest value representable in your implementation’s double type to the decimal number 255.167715, because the double type has only 53-bit significands. (A significand is the fraction portion of a floating-point number. There is also a sign and an exponent portion.)
Then, for float a = 255.167715;, this double value is converted to float. Since the float type has only 24-bit significands, the result is 11111111.00101010111011112, which is 255.1677093505859375 in decimal.
When you print this with the default formatting of %f, six digits after the decimal place are used, so it prints “255.167709”.
The short answer is that there is no such single-precision floating-point number as 255.167715. This is true for any computer using IEEE 754 floating-point formats; the situation is not unique to C. As a single-precision floating-point number, the closest value is 255.167709.
Single-precision floating point gives you the equivalent of 7 or so decimal digits of precision. And as you can see, the input you gave and the output you got agreed to seven places, namely 255.1677. Any digits past that are essentially meaningless.
For much more about the sometimes-surprising aspects of floating-point math, see "Is floating point math broken?".

Explain the output when converting Float to integer? [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 8 years ago.
I exactly don't know how why output is coming
float f=1.4, t;
int d,s;
d=(int)f;
printf("d=%d\n",d);
t=f-d;
printf("t=%f\n",t);
t=t*10;
printf("t=%f\n",t);
s=(int)t;
printf("s=%d\n",s);
the output is
d=1
t=0.400000
t=4.000000
s=3
and similarly when f=1.1
the output is
d=1
t=0.100000
t=1.000000
s=1
Is this related to the way the integer and float is stored in the memory or something else ?
You have initialized f=1.4, not when you do
d=(int)f;
You are converting float to integer, and when float is converted to integer, all the number after period "." are truncated. Now d has 1 so
t=f-d;
will be 1.4 - 1 = 0.4
t=t*10;
t=0.4*10=4 and as t is float so it outputs 4.0000
Float represent trailing zeros at the end
s=(int)t;
Here again you are converting float to integer, Now here is tricky part, All the values above are rounded off, here t has value 3.99999976 so when converted to integer it shows 3 as a result
This is all because when you initialize t=1.4, in actual it is initialized to 1.39999998
During the first assignment
float f=1.4;
there is an approximation because 1.4 is intended as double (not float). Something like 1.39999999 is assigned to f.
Try to use
float f=1.4f;
and it should work as you expect.
Let's take it step-by-step and see how floating point and int interact.
Assume a typical platform where
float is IEEE 754 single-precision binary floating-point format and
double is IEEE 754 double-precision binary floating-point format
float f=1.4, t;
// 1.4 isn't exactly representable in FP & takes on the closest `double` value of
// 1.399999999999999911182158029987476766109466552734375
// which when assigned to a float becomes
// 1.39999997615814208984375
int d,s;
d=(int)f;
// d gets the truncated value of 1 and prints 1, no surprise.
printf("d=%d\n",d);
t=f-d;
// t gets the value 0.39999997615814208984375
// A (double) version of t, with the same value is passed to printf()
// This is printed out, rounded to 6 (default) decimal places after the '.' as
// 0.400000
printf("t=%f\n",t);
t=t*10;
// t is multiplied by exactly 10 and gets the value
// 3.9999997615814208984375
// A (double) version of t, with the same value is passed to printf()
// which prints out, rounded to 6 decimal places after the '.' as
// 4.00000.
printf("t=%f\n",t);
s=(int)t;
// s gets the truncated value of 3.9999997615814208984375
// which is 3 and prints out 3. - A bit of a surprise.
printf("s=%d\n",s);

Float and double output [duplicate]

This question already has answers here:
strange output in comparison of float with float literal
(8 answers)
Closed 9 years ago.
Please explain the output for different cases
#include<stdio.h>
int main()
{
float a=5.9; //a=0.9
if (a==5.9)
printf("Equal");
else if (a<5.9)
printf("Less than");
else
printf("Greater than");
return 0;
}
When a is 5.9 the output is "Greater than", when a is 0.9 the output is "Less than". Why?
In C, the literal “5.9” has type double and is converted by common compilers to 5.9000000000000003552713678800500929355621337890625, because they use binary IEEE-754 floating point, and that number is the value representable as a double that is closest to 5.9. Your code initializes a float with that value. That requires converting a double to a float, and the result is 5.900000095367431640625, because that is the float value that is closest to the double value. Obviously, the latter is greater than the former, which is why your output is “Greater than”.
With .9, the literal “.9” is converted to the double 0.90000000000000002220446049250313080847263336181640625. Then that double is converted to the float 0.89999997615814208984375, which is obviously less than the double.
Your variable is a float but the constant is a double. Since that value can't be stored precisely ti will be stored differently as a float and as a double. If you use the same data types you'll get the desired results
http://codepad.org/1q5mwFGd
http://codepad.org/Q4lOQnG8
Floating point numbers are inherently imprecise. For a quick introduction, you can read up a bit here. http://floating-point-gui.de/errors/comparison/
For some suggestions on effective comparison strategies, see this post. What is the most effective way for float and double comparison?
This is because internally, the floating point numbers are stored in binary form and 5.9 can't be represented exactly as 5.9. Have a look at the following similar question and answer: Why does a C floating-point type modify the actual input of 125.1 to 125.099998 on output?
When comparing floating-point numbers it is best to avoid '=='.
This because some values cannot be correctly stored without some loss of precision.
So it is better to say:
if( fabs(a-5.9) < .0001 ) {
// 'EQUAL' or at least near enough!
}
I know this takes more to compute, but it will behave the way you expect.
Due to decimal binary conversion, 0.9 represented as a summation of powers of 2^-1:
0.9 - (0.5 + 0.25 + 0.125) = 0.025
But 0.025 is not an exact power of 2^-1. So you need to represent both numbers in the comparison with the same precision. Since float and double have different precision they compare not equal.

float - c data types

int main() {
float a = 20000000;
float b = 1;
float c = a+b;
if (c==a) { printf("equal"); }
else { printf("not equal");}
return 0;
}
when I run this it says "equal".
but when I change the value of a to 2000000 (one zero less) the answer is no.
why ?
Typically, a float has a precision of 24 bits. The number 20000001 = 0x1312d01 needs 25 bits to be represented exactly, so it must be rounded. The normal rounding mode for values exactly half-way between two representable values is rounding to last-bit-zero, hence 20000001 is rounded to 20000000 as a float.
2000001 = 0x1e8481 needs fewer than 24 bits to be represented (21), so there is no rounding needed for that.
Floating point numbers are very often approximate values instead of exact values. You can read all about it here:
http://en.wikipedia.org/wiki/Floating_point
If you declare two variable as of type float and then even you put those two value same. You would get unpredictable result if you compare for equality. For more details google for IEEE standard (IEEE 754) for representing floating point number.
wikipedia article
Precision of float.
What range of numbers can be represented in a 16-, 32- and 64-bit IEEE-754 systems?
http://en.wikipedia.org/wiki/Floating_point
http://en.wikipedia.org/wiki/Single-precision_floating-point_format

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