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
Related
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.
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).
#include<stdio.h>
int main()
{
float f = 0.1;
double d = 0.1;
printf("%lu %lu %lu %lu\n", sizeof(f), sizeof(0.1f), sizeof(0.1), sizeof(d));
return 0;
}
Output
$ ./a.out
4 4 8 8
As per above code, we can see sizeof(0.1) and sizeof(0.1f) are not same.
sizeof(0.1) is 8 bytes, while sizeof(0.1f) is 4 bytes.
but while assigning the value to float variable f, it automatically truncates its size to 4 bytes.
While in below code, while comparing it with float x it is not truncating and 4 bytes of float are compared with 8 bytes of 0.1, value of float x matches with 0.1f as both are of 4 bytes.
#include<stdio.h>
int main()
{
float x = 0.1;
if (x == 0.1)
printf("IF");
else if (x == 0.1f)
printf("ELSE IF");
else
printf("ELSE");
}
Output
$ ./a.out
ELSE IF
why and how it is truncating while assigning and not while comparing?
A floating point literal without a suffix is of type double. Suffixing it with an f makes a literal of type float.
When assigning to a variable, the right operand to = is converted to the type of the left operand, thus you observe truncation.
When comparing, the operands to == are converted to the larger of the two operands, so x == 0.1 is like (double)x == 0.1, which is false since (double)(float)0.1 is not equal to 0.1 due to rounding issues. In x == 0.1f, both operands have type float, which results in equality on your machine.
Floating point math is tricky, read the standard for more details.
a floating point constant like 0.1 is a double unless specified as a float like 0.1f. The line
float f = 0.1;
means create a double with value 0.1 and cast it to float and lose precision in the process. The lines
float x = 0.1;
if (x == 0.1)
will cause x to be implicitly converted to double but it will have a slightly different value than for e.g. double x = 0.1;
0.1f (the "f" after the number) is for the computer as float , that how your compailer know that he need to store it as float and not as double.
so float 0.1 not equal to 0.1 , its equal to 0.1f
when you write 0.1 , it is considered by default as double. suffix f explicitly make it float.
In second question float are stored as ieee standard so it it's going in else if because equivalent conversion of 0.1f to double is not same.
https://en.wikipedia.org/wiki/Floating_point
0.1 is a double value whereas 0.1f is a float value.
The reason we can write float x=0.1 as well as double x=0.1 is due to implicit conversions .
But by using suffix f you make it a float type .
In this -
if(x == 0.1)
is flase because 0.1 is not exactly 0.1 at some places after decimal .There is also conversion in this to higher type i.e double.
Converting to float and then to double , there is loss of information as also double as higher precession than float so it differs .
In C, when ±0.0 is supported, -0.0 or +0.0 assigned to a double typically makes no arithmetic difference. Although they have different bit patterns, they arithmetically compare as equal.
double zp = +0.0;
double zn = -0.0;
printf("0 == memcmp %d\n", 0 == memcmp(&zn, &zp, sizeof zp));// --> 0 == memcmp 0
printf("== %d\n", zn == zp); // --> == 1
Inspire by a #Pascal Cuoq comment, I am looking for a few more functions in standard C that provide arithmetically different results.
Note: Many functions, like sin(), return +0.0 from f(+0.0) and -0.0 from f(-0.0). But these do not provide different arithmetic results. Also the 2 results should not both be NaN.
There are a few standard operations and functions that form numerically different answers between f(+0.0) and f(-0.0).
Different rounding modes or other floating point implementations may give different results.
#include <math.h>
double inverse(double x) { return 1/x; }
double atan2m1(double y) { return atan2(y, -1.0); }
double sprintf_d(double x) {
char buf[20];
// sprintf(buf, "%+f", x); Changed to e
sprintf(buf, "%+e", x);
return buf[0]; // returns `+` or `-`
}
double copysign_1(double x) { return copysign(1.0, x); }
double signbit_d(double x) {
int sign = signbit(x); // my compile returns 0 or INT_MIN
return sign;
}
double pow_m1(double x) { return pow(x, -1.0); }
void zero_test(const char *name, double (*f)(double)) {
double fzp = (f)(+0.0);
double fzn = (f)(-0.0);
int differ = fzp != fzn;
if (fzp != fzp && fzn != fzn) differ = 0; // if both NAN
printf("%-15s f(+0):%-+15e %s f(-0):%-+15e\n",
name, fzp, differ ? "!=" : "==", fzn);
}
void zero_tests(void) {
zero_test("1/x", inverse);
zero_test("atan2(x,-1)", atan2m1);
zero_test("printf(\"%+e\")", sprintf_d);
zero_test("copysign(x,1)", copysign_1);
zero_test("signbit()", signbit_d);
zero_test("pow(x,-odd)", pow_m1);; // #Pascal Cuoq
zero_test("tgamma(x)", tgamma); // #vinc17 #Pascal Cuoq
}
Output:
1/x f(+0):+inf != f(-0):-inf
atan2(x,-1) f(+0):+3.141593e+00 != f(-0):-3.141593e+00
printf("%+e") f(+0):+4.300000e+01 != f(-0):+4.500000e+01
copysign(x,1) f(+0):+1.000000e+00 != f(-0):-1.000000e+00
signbit() f(+0):+0.000000e+00 != f(-0):-2.147484e+09
pow(x,-odd) f(+0):+inf != f(-0):-inf
tgamma(x) f(+0):+inf != f(-0):+inf
Notes:
tgamma(x) came up == on my gcc 4.8.2 machine, but correctly != on others.
rsqrt(), AKA 1/sqrt() is a maybe future C standard function. May/may not also work.
double zero = +0.0; memcpy(&zero, &x, sizeof x) can show x is a different bit pattern than +0.0 but x could still be a +0.0. I think some FP formats have many bit patterns that are +0.0 and -0.0. TBD.
This is a self-answer as provided by https://stackoverflow.com/help/self-answer.
The IEEE 754-2008 function rsqrt (that will be in the future ISO C standard) returns ±∞ on ±0, which is quite surprising. And tgamma also returns ±∞ on ±0. With MPFR, mpfr_digamma returns the opposite of ±∞ on ±0.
I think about this method, but I can't check before weekend, so someone might do some experiments on this, if he/she like, or just tell me that it is nonsense:
Generate a -0.0f. It should be possible to generate staticly by a assigning a tiny negative constant that underflows float representation.
Assign this constant to a volatile double and back to float.
By changing the bit representation 2 times, I assume that the
compiler specific standard bit representation for -0.0f is now in the
variable. The compiler can't outsmart me there, because a totally
other value could be in the volatile variable between those 2 copies.
compare the input to 0.0f. To detect if we have a 0.0f/-0.0f case
if it is equal, assign the input volitale double variable, and then back to float.
I again assume that it has now standard compiler representation for 0.0f
access the bit patterns by a union and compare them, to decide if it is -0.0f
The code might be something like:
typedef union
{
float fvalue;
/* assuming int has at least the same number of bits as float */
unsigned int bitpat;
} tBitAccess;
float my_signf(float x)
{
/* assuming double has smaller min and
other bit representation than float */
volatile double refitbits;
tBitAccess tmp;
unsigned int pat0, patX;
if (x < 0.0f) return -1.0f;
if (x > 0.0f) return 1.0f;
refitbits = (double) (float) -DBL_MIN;
tmp.fvalue = (float) refitbits;
pat0 = tmp.bitpat;
refitbits = (double) x;
tmp.fvalue = (float) refitbits;
patX = tmp.bitpat;
return (patX == pat0)? -1.0f : 1.0f;
}
It is not a standard function, or an operator, but a function that should differentiate between signs of -0.0 and 0.0.
It based (mainly) on the assumption that the compiler vendor does not use different bit patterns for -0.0f as result of changing of formats, even if the floating point format would allow it, and if this holds, it is independent from the chosen bit pattern.
For a floating point formats that have exact one pattern for -0.0f this function should safely do the trick without knowledge of the bit ordering in that pattern.
The other assumptions (about size of the types and so on) can be handled with precompiler switches on the float.h constants.
Edit: On a second thought: If we can force the value comparing to (0.0 || -0.0) below the smallest representable denormal (subnormal) floating point number or its negative counterpart, and there is no second pattern for -0.0f (exact) in the FP format, we could drop the casting to volatile double. (But maybe keep the float volatile, to ensure that with deactivated denormals the compiler can't do any fancy trick, to ignore operations, that reduce any further the absolut value of things comparing equal to 0.0.)
The Code then might look like:
typedef union
{
float fvalue;
/* assuming int has at least the same number of bits as float */
unsigned int bitpat;
} tBitAccess;
float my_signf(float x)
{
volatile tBitAccess tmp;
unsigned int pat0, patX;
if (x < 0.0f) return -1.0f;
if (x > 0.0f) return 1.0f;
tmp.fvalue = -DBL_MIN;
/* forcing something compares equal to 0.0f below smallest subnormal
- not sure if one abs()-factor is enough */
tmp.fvalue = tmp.fvalue * fabsf(tmp.fvalue);
pat0 = tmp.bitpat;
tmp.fvalue = x;
tmp.fvalue = tmp.fvalue * fabsf(tmp.fvalue);
patX = tmp.bitpat;
return (patX == pat0)? -1.0f : 1.0f;
}
This might not work with fancy rounding methods, that prevent rounding from negative values towards -0.0.
Not exactly an answer to the question, but can be useful to know:
Just faced the case a - b = c => b = a - c, which fails to hold if a is 0.0 and b is -0.0. We have 0.0 - (-0.0) = 0.0 => b = 0.0 - 0.0 = 0.0. The sign is lost. The -0.0 is not recovered.
Taken from here.
int main()
{
float lfResult = 19.893196;
if(lfResult == 19.893196)
printf("Works");
else
printf("does not work");
getch();
return 0;
}
Output: does not work
Why does the if condition fail?
In C floating constants have the type double. Try:
float lfResult = 19.893196f;
if(lfResult == 19.893196f)
^
Thus the constant 19.893196 has more precision than lfResult.
6.4.4.2 - 4
An unsuffixed floating constant has type double. If suffixed by the
letter f or F, it has type float. If suffixed by the letter l or L, it
has type long double.
your literal is a double, casted to float in assignement.
try:
if(lfResult == 19.893196F)
...
In if condition, 19.893196 can be taken as double. So the if condition fails.
You should try like following way.
if(lfResult == 19.893196f)
I think it will be helpful to you.