float num1 = 1;
if (num1 == 1)
{
printf("Yes, it is equal!!\n");
}
else
{
printf("No, it is not equal\n");
}
output --> Yes, it is equal!
whereas
float num1 = 1.2;
if (num1 == 1.2)
{
printf("Yes, it is equal!!\n");
}
else
{
printf("No, it is not equal\n");
}
output --> No, it is not equal
but why?
Please explain in detail.
In spite of your title, there is no comparison with any int value.
num == 1.2 compares the float value in num with the double value of 1.2.
When 1.2 is converted to double in your C implementation, it is converted to the nearest representable value. Since your C implementation uses a binary-based system for floating-point, it cannot exactly represent 1.2, and there is a small error in the conversion.
In float num1 = 1.2;, the double value resulting from 1.2 is converted again, this time to float. Since float has less precision than double, there is even more error. The result is that the float num1 is not equal to the double 1.2.
Thus, the comparison num1 == 1.2 evaluates to false.
Be very careful in exact comparison of float numbers. No all values can be presented as float exactly, because not all values can be presented as finite sum of components being power (positive or negative) of 2. The same problem is about double.
There is no good and universal solution for your problem, it strongly depends to kind of possible values, expected accuracy etc.
Probably you should move into integer values, for example by multyplying your floats by some power of 10, then convert (round) to int, and - finally - compare.
Related
The output of the following code is 0.0000000:
#include <stdio.h>
int main() {
float x;
x = (float)3.3 == 3.3;
printf("%f", x);
return 0;
}
Whereas this code outputs 1.000000:
int main() {
float x;
x = (float)3.5 == 3.5;
printf("%f", x);
return 0;
}
The only difference between the 2 codes is the value in the comparison, however, the results are not the same, why is this?
This line:
x=(float)3.3==3.3;
Compares (float)3.3 and 3.3 for equality and assigns the result to x. The left side of the comparison has type float because of the cast, while the right side has type double which is the default type for floating point constants.
The value 3.3 cannot be represented exactly in binary floating point, so the actual value stored is an approximation. This approximated value will be different for types float and double due to their differing precisions, so the equality will evaluated to false, i.e. 0. This is the value that gets assigned to x.
Regarding your comment on why x is 1 when the number you're checking is 3.5, that is because 3.5 can be represented exactly in binary, and both types have the precision to store that value, so they compare equal.
The assigned value 3.3 is a type of double but you're trying to compare a double with a float (by typecasting and due to this, precision losses).
The value of 3.3 as double is 3.299999999999999822 whereas the same value in float is measured 3.299999952F which are clearly unequal. Hence, the result will be true (i.e. 1.0000000) if you typecast the other 3.3 as float.
Rather than:
x = (float) 3.3 == 3.3; // float != double precision (precision loss)
If you do this:
x = (float) 3.3 == (float) 3.3; // converting both to make precision equal
Or,
x = (double) 3.3 == (double) 3.3; // converting . . . (same)
In other words, the comparison will be equal if you convert any one of the expression as same as the other one.
Also, notice that 3.5 is equal to 3.50000000... in both float and double, hence all the trailing zeroes are truncated from the assigned variable and hence you get 1.0000000. But this stuff is just a bit contrary with 3.3.
float has less precision than double, the value of 3.3 constant defaults to double and is 3.299999999999999822, the same constant when converted to float is 3.29999995231628418.
3.299999999999999822 == 3.29999995231628418 the result of this comparison is false i.e. 0.
Given the precedence rules, the expresssion amounts to x = ((float)3.5 == 3.5);, the comparison is evaluated first and the result is assigned to x.
When there is no cast both constants default to double so naturally the result of the comparison between them is true i.e. 1.
Regarding the comparison between 3.5 double and float being true, it has to do with the binary conversion, 3.3 is subjected to an aproximation given the fact that the mantissa conversion would go on indefinitely as can be seen in the link above, the exact value simply cannot be represented in double nor in float, whereas 3.5 is perfectly representable both in double and float alike.
To see loss of precision with float:
#include <stdio.h>
int main(){
float x = 3.3;
double d = 3.3;
printf("%12.9f %12.9lf\n",x, d);
Output:
3.299999952 3.300000000
3.3 in binary is
11.0100110011001100110011001100110011001100110011
When converted to float some bits of precision are truncated
11.0100110011001100110011001100110
When converted back to double, computer just uses 0's
11.0100110011001100110011001100110000000000000000
So
3.3 11.0100110011001100110011001100110011001100110011
(float)3.3 11.0100110011001100110011001100110
(double)((float)3.3) 11.0100110011001100110011001100110000000000000000
3.5 for comparison
3.5 11.1000000000000000000000000000000000000000000000
(float)3.5 11.1000000000000000000000000000000
(double)((float)3.5) 11.1000000000000000000000000000000000000000000000
Values like 3.3 cannot be represented exactly in a finite number of bits, just like the result of 1/3 cannot be represented exactly in a finite number of decimal digits, so you wind up storing an approximation of the value.
The float approximation is different from the double approximation, so the comparison (float) 3.3 == 3.3 fails.
By contrast, 3.5 can be represented exactly in both float and double types, so the comparison (float) 3.5 == 3.5 succeeds.
Just like with integer types, the significand of a floating-point type is a sum of powers of 2 - the value 3.5 is represented as 1.75 * 21, and the binary representation of the significand 1.75 is 1.112 - 1 * 20 + 1 * 2-1 + 1 * 2-2, or 1 + 0.5 + 0.25.
The issue is that you loose precision when converting the value 3.3, which is a literal of type double, to a float value with the cast (float)3.3. This loss of precision is irreversible, even if the comparison operator == will promote the left operand back to type double.
So the issue is that
(double)((float)3.3) == (double)3.3
will be false since the cast of 3.3 to float looses precision. For 3.5, in contrast, the result will be true, because 3.5 can be exactly represented as float in the same precision as double can.
Actually, the situation can be compared to casting a value from a higher rank to a lower and then back like in the following snippet:
unsigned int x = 257;
unsigned char y = x;
unsigned int x2 = y;
printf("%d\n", x==x2); // 0
x = 255;
y = x;
x2 = y;
printf("%d\n", x==x2); // 1
This question already has answers here:
Why are floating point numbers inaccurate?
(5 answers)
Closed 6 years ago.
#include<stdio.h>
void main()
{
float a = 2.3;
if(a == 2.3) {
pritnf("hello");
}
else {
printf("hi");
}
}
It prints "hi" in output, or we can say that if condition is getting false value.
#include<stdio.h>
void main()
{
float a = 2.5;
if(a == 2.5)
printf("Hello");
else
printf("Hi");
}
It prints hello.
The variable a is a float that holds some value close to the mathematical value 2.3.
The literal 2.3 is a double that also holds some value close to the mathematical value 2.3, but because double has greater precision than float, this may be a different value from the value of a. Both float and double can only represent a finite number of values, so there are necessarily mathematical real numbers that cannot be represented exactly by either of those two types.
In the comparison a == 2.3, the left operand is promoted from float to double. This promotion is exact and preserves the value (as all promotions do), but as discussed above, that value may be a different one from that of the 2.3 literal.
To make a comparison between floats, you can use an appropriate float literal:
assert(a == 2.3f);
// ^
2.3 with binary representation is 01000000000100110011001100110011...
so you are not able to set a float exactly to 2.3
with double precision you get something similar: 2.299999952316284
you converted a double to float when you wrote:
float a = 2.3;
the if checks if the float a is equal to double 2.299999952316284
you should write:
float a = 2.3f;
and you can check:
if (a == 2.3f) {
...
}
i would rather test with:
if (fabs(a - 2.3f) < 0.00001) {
...
}
the 2.5 represented with bits is: 01000000001000000000000000000000
EDIT: fabs is part of the <math.h> or <cmath>
Read this: article
Comparing floating point values is not as easy as it might seem, have a look at Most effective way for float and double comparison.
It all boils down to the fact, that floating point numbers are not exact (well
most are not). Usually you compare 2 floats by allowing a small error window (epsilon):
if( fabs(a - 2.3f) < epsion) { ... }
where epsilon is small enough for your calculation, but not too small (bigger than Machine epsilon).
This question already has answers here:
Comparing float and double
(3 answers)
Closed 7 years ago.
int main(void)
{
float me = 1.1;
double you = 1.1;
if ( me == you ) {
printf("I love U");
} else {
printf("I hate U");
}
}
This prints "I hate U". Why?
Floats use binary fraction. If you convert 1.1 to float, this will result in a binary representation.
Each bit right if the binary point halves the weight of the digit, as much as for decimal, it divides by ten. Bits left of the point double (times ten for decimal).
in decimal: ... 0*2 + 1*1 + 0*0.5 + 0*0.25 + 0*0.125 + 1*0.0625 + ...
binary: 0 1 . 0 0 0 1 ...
2's exp: 1 0 -1 -2 -3 -4
(exponent to the power of 2)
Problem is that 1.1 cannot be converted exactly to binary representation. For double, there are, however, more significant digits than for float.
If you compare the values, first, the float is converted to double. But as the computer does not know about the original decimal value, it simply fills the trailing digits of the new double with all 0, while the double value is more precise. So both do compare not equal.
This is a common pitfall when using floats. For this and other reasons (e.g. rounding errors), you should not use exact comparison for equal/unequal), but a ranged compare using the smallest value different from 0:
#include "float.h"
...
// check for "almost equal"
if ( fabs(fval - dval) <= FLT_EPSILON )
...
Note the usage of FLT_EPSILON, which is the aforementioned value for single precision float values. Also note the <=, not <, as the latter will actually require exact match).
If you compare two doubles, you might use DBL_EPSILON, but be careful with that.
Depending on intermediate calculations, the tolerance has to be increased (you cannot reduce it further than epsilon), as rounding errors, etc. will sum up. Floats in general are not forgiving with wrong assumptions about precision, conversion and rounding.
Edit:
As suggested by #chux, this might not work as expected for larger values, as you have to scale EPSILON according to the exponents. This conforms to what I stated: float comparision is not that simple as integer comparison. Think about before comparing.
In short, you should NOT use == to compare floating points.
for example
float i = 1.1; // or double
float j = 1.1; // or double
This argument
(i==j) == true // is not always valid
for a correct comparison you should use epsilon (very small number):
(abs(i-j)<epsilon)== true // this argument is valid
The question simplifies to why do me and you have different values?
Usually, C floating point is based on a binary representation. Many compilers & hardware follow IEEE 754 binary32 and binary64. Rare machines use a decimal, base-16 or other floating point representation.
OP's machine certainly does not represent 1.1 exactly as 1.1, but to the nearest representable floating point number.
Consider the below which prints out me and you to high precision. The previous representable floating point numbers are also shown. It is easy to see me != you.
#include <math.h>
#include <stdio.h>
int main(void) {
float me = 1.1;
double you = 1.1;
printf("%.50f\n", nextafterf(me,0)); // previous float value
printf("%.50f\n", me);
printf("%.50f\n", nextafter(you,0)); // previous double value
printf("%.50f\n", you);
1.09999990463256835937500000000000000000000000000000
1.10000002384185791015625000000000000000000000000000
1.09999999999999986677323704498121514916420000000000
1.10000000000000008881784197001252323389053300000000
But it is more complicated: C allows code to use higher precision for intermediate calculations depending on FLT_EVAL_METHOD. So on another machine, where FLT_EVAL_METHOD==1 (evaluate all FP to double), the compare test may pass.
Comparing for exact equality is rarely used in floating point code, aside from comparison to 0.0. More often code uses an ordered compare a < b. Comparing for approximate equality involves another parameter to control how near. #R.. has a good answer on that.
Because you are comparing two Floating point!
Floating point comparison is not exact because of Rounding Errors. Simple values like 1.1 or 9.0 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. For example:
float a = 9.0 + 16.0
double b = 25.0
if(a == b) // can be false!
if(a >= b) // can also be false!
Even
if(abs(a-b) < 0.0001) // wrong - don't do this
This is a bad way to do it because a fixed epsilon (0.0001) is chosen because it “looks small”, could actually be way too large when the numbers being compared are very small as well.
I personally use the following method, may be this will help you:
#include <iostream> // std::cout
#include <cmath> // std::abs
#include <algorithm> // std::min
using namespace std;
#define MIN_NORMAL 1.17549435E-38f
#define MAX_VALUE 3.4028235E38f
bool nearlyEqual(float a, float b, float epsilon) {
float absA = std::abs(a);
float absB = std::abs(b);
float diff = std::abs(a - b);
if (a == b) {
return true;
} else if (a == 0 || b == 0 || diff < MIN_NORMAL) {
return diff < (epsilon * MIN_NORMAL);
} else {
return diff / std::min(absA + absB, MAX_VALUE) < epsilon;
}
}
This method passes tests for many important special cases, for different a, b and epsilon.
And don't forget to read What Every Computer Scientist Should Know About Floating-Point Arithmetic!
This question already has answers here:
Checking if float is an integer
(8 answers)
Closed 8 years ago.
I have a program in which i need to print FLOAT in case of a float number or print INTEGER in case of a regular number.
for Example pseudo code
float num = 1.5;
if (num mod sizeof(int)==0)
printf ("INTEGER");
else
printf("FLOAT");
For example:
1.6 would print "FLOAT"
1.0 would print "INTEGER"
Will something like this work?
All float types have the same size, so your method won't work. You can check if a float is an integer by using ceilf
float num = 1.5;
if (ceilf(num) == num)
printf ("INTEGER");
else
printf("FLOAT");
You can use modff():
const char * foo (float num) {
float x;
modff(num, &x);
return (num == x) ? "INTEGER" : "FLOAT";
}
modff() will take a float argument, and break it into its integer and fractional parts. It stores the integer part in the second argument, and the fractional part is returned.
The "easy" way, but with a catch:
You could use roundf, like this:
float z = 1.0f;
if (roundf(z) == z) {
printf("integer\n");
} else {
printf("fraction\n");
}
The problem with this and other similar techniques (such as ceilf) is that, while they work great for whole number constants, they will fail if the number is a result of a calculation that was subject to floating-point round-off error. For example:
float z = powf(powf(3.0f, 0.05f), 20.0f);
if (roundf(z) == z) {
printf("integer\n");
} else {
printf("fraction\n");
}
Prints "fraction", even though (31/20)20 should equal 3, because the actual calculation result ended up being 2.9999992847442626953125.
So how do we deal with this?
Any similar method, be it fmodf or whatever, is subject to this. In applications that perform complex or rounding-prone calculations, usually what you want to do is define some "tolerance" value for what constitutes a "whole number" (this goes for floating-point equality comparisons in general). We often call this tolerance epsilon. For example, lets say that we'll forgive the computer for up to +/- 0.00001 rounding error. Then, if we are testing z, we can choose an epsilon of 0.00001 and do:
if (fabsf(roundf(z) - z) <= 0.00001f) {
printf("integer\n");
} else {
printf("fraction\n");
}
You don't really want to use ceilf here because e.g. ceilf(1.0000001) is 2 not 1, and ceilf(-1.99999999) is -1 not -2.
Choose a tolerance value that is appropriate for your application. For more information, check out this article on comparing floating-point numbers.
Will something like this work?
No. For example on the x86_32 and ARM 32 bit architectures sizeof(int) == 4 and sizeof(float) == 4.
Also whatever you think mod is, it clearly shows you don't understand what the sizeof operator does.
I am wondering what the difference is between these two variables in C:
float price = 3.00;
and
float price = 3.00f;
What is the use of suffix f in this case?
3.00 is interpreted as a double, as opposed to 3.00f which is seen by the compiler as a float.
The f suffix simply tells the compiler which is a float and which is a double.
See MSDN (C++)
In addition to what has already been said, keeping track of 1.0 versus 1.0f is more important than many people realize. If you write code like this:
float x;
...
float y = x * 2.0;
Then x will be promoted to a double, because 2.0 is a double. The compiler is not allowed to optimize that promotion away or it would violate the C standard. The calculation takes place with double precision, and then the result is then implicitly truncated into a float. This means that the calculation will be slower (though more accurate) than it would have been if you had written 2.0f or 2.
Had you written 2, the constant would be of int type, which would be promoted to a float, and the calculation would have been done with "float precision". A good compiler would warn you about this promotion.
Read more about the "usual arithmetic conversion" rules here:
http://msdn.microsoft.com/en-us/library/3t4w2bkb%28v=vs.80%29.aspx
Because by unsuffixed floating-point literals are doubles, and rounding means that even small literals can take on different values when rounded to float and double. This can be observed in the following example:
float f=0.67;
if(f == 0.67)
printf("yes");
else
printf("no");
This will output no, because 0.67 has a different value when rounded to float than it does when rounded to double. On the other hand:
float f=0.67;
if(f == 0.67f)
printf("yes");
else
printf("no");
outputs yes.
The suffix can be specified using either upper or lowercase letters.
Try this also:
printf(" %u %u\n", sizeof(.67f), sizeof(.67));
Check #codepade
3.00 is a double, 3.00f is a float.
Adding few more combination of comparisons between float and double data types.
int main()
{
// Double type constant(3.14) converts to Float type by
// truncating it's bits representation
float a = 3.14;
// Problem: float type 'a' promotes to double type and the value
// of 'a' depends on how many bits added to represent it.
if(a == 3.14)
std::cout<<"a: Equal"<<std::endl;
else
std::cout<<"a: Not Equal"<<std::endl;
float b = 3.14f; // No type conversion
if(b == 3.14) // Problem: Float to Double conversion
std::cout<<"b: Equal"<<std::endl;
else
std::cout<<"b: Not Equal"<<std::endl;
float c = 3.14; // Double to Float conversion (OK even though is not a good practice )
if(c == 3.14f) // No type conversion
std::cout<<"c: Equal"<<std::endl; // OK
else
std::cout<<"c: Not Equal"<<std::endl;
float d = 3.14f;
if(d == 3.14f)
std::cout<<"d: Equal"<<std::endl; // OK
else
std::cout<<"d: Not Equal"<<std::endl;
return 0;
}
Output:
a: Not Equal
b: Not Equal
c: Equal
d: Equal
That's because the default type of a
floating point numeric literal - the
characters 3.00 is double not float.
To make this compile you have to add
the suffix f (or F).
Often the difference isn't important, as the compiler will convert the double constant into a float anyway. However, consider this:
template<class T> T min(T a, T b)
{
return (a < b) ? a : b;
}
float x = min(3.0f, 2.0f); // will compile
x = min(3.0f, 2); // compiler cannot deduce T type
x = min(3.0f, 2.0); // compiler cannot deduce T type