What is the type of a floating-point literal having an exponent part, such as the 123456e-3 in C(99+)? Is it of type float or double? When used as a float initializer in float f = 123456e-3;
does it need to have a f suffix?
What is the type of a floating-point literal having an exponent part, such as the 123456e-3 in C(99+)? Is it of type float or double? When used as a float initializer in float f = 123456e-3;
does it need to have a f suffix?
By default, all floating point literals, with or without an exponent part, have type double. You can add the f suffix to make the type float or L to make the type long double.
In the case of float f = 123456e-3;, you're initializing a float with a double constant, so there is the possibility of loss of precision, however this particular constant only has 6 decimal digits of precision so it should be OK.
For floating point literal, if no suffix is defined, it will be automatically considered as double.
You can follow this chart for suffix:
(no suffix) - double
f/F - float
l/L - long double
So, for float, it needs to have f or F suffix.
What is the type of a floating-point literal?
Floating constants
C defines these as floating constants, not literals. Default type is double.
An f or F suffix makes it a float.
An l or L suffix makes it a long double.
[edit] FLT_EVAL_METHOD
C has FLT_EVAL_METHOD which allows constants to be interpreted as a wider type.
Example FLT_EVAL_METHOD == 2
evaluate all operations and constants to the range and precision of the
long doubletype.
In this case, I'd expect v1 and v2 to have the same value when FLT_EVAL_METHOD == 2, but different values when FLT_EVAL_METHOD == 0.
long double v1 = 0.1;
long double v2 = 0.1L;
When used as a float initializer in float f = 123456e-3; does it need to have a f suffix?
For best conversion of the text to float, yes use an f.
float f = 123456e-3 incurs double rounding. 2 rounding occurs: text->double and double to float.
With select values, g may get a different value with float g = x.xxx vs g = x.xxxf;. See following.
double rounding example
Notice f2 and f4 have the same constant except the the f suffix. Compiler warns with f4:
warning: conversion from 'double' to 'float' changes value from '9.9999997019767761e-1' to '1.0e+0f' [-Wfloat-conversion]
#include <stdlib.h>
int main(void) {
// float has 24 bit significand, double has 53
float f1 = 0x0.FFFFFFp0f; // code with 24 bit significand, exact as a float
printf("%-20a %.17e\n", f1, f1);
float f2 = 0x0.FFFFFF7FFFFFFCp0f; // code with 54 bit significand, rounds down to nearest float
printf("%-20a %.17e\n", f2, f2);
float f3 = 0x0.FFFFFF80000000p0f; // code with 25 bit significand, rounds up to nearest float
printf("%-20a %.17e\n", f3, f3);
puts("");
double d1 = 0x0.FFFFFF7FFFFFF8p0; // code constant with 53 bit significand, exact as a double
printf("%-20a %.17e\n", d1, d1);
double d2 = 0x0.FFFFFF7FFFFFFCp0; // code constant with 54 bit significand, rounds up to nearest double
printf("%-20a %.17e\n", d2, d2);
float f4 = 0x0.FFFFFF7FFFFFFCp0; // code constant with 54 bit significand, rounds up to nearest double
// then rounds up again when double converted to float
printf("%-20a %.17e\n", f4, f4);
return 0;
}
Output
0x1.fffffep-1 9.99999940395355225e-01
0x1.fffffep-1 9.99999940395355225e-01 f2
0x1p+0 1.00000000000000000e+00
0x1.fffffefffffffp-1 9.99999970197677501e-01
0x1.ffffffp-1 9.99999970197677612e-01
0x1p+0 1.00000000000000000e+00 f4 Double Rounding!
For best conversion of the text to long double, definitely use an L else the constant is only a double with less precision.
long double ld1 = 0x1.00000000000001p1;
printf("%.20Le\n", ld1, ld1);
long double ld2 = 0x1.00000000000001p1L; // "Same" constant as above with an 'L'
printf("%.20Le\n", ld2, ld2);
Output
2.00000000000000000000e+00
2.00000000000000002776e+00