2

I know that according to the single point standard IEEE the maximum value of a float is 1.11111111111111111111111 *2^127 which converted in decimal is exactly this huge number -> 340282346638528859811704183484516925440.

How came that I get the error "integer literal is too large to be represented in any integer type" when trying to assign this value to a float like this :

int main(){

float biggest=340282346638528859811704183484516925440;

}

Shouldn't the compiler say "ok, this is the maximum value for a single float point number and I have to convert it to the 32bit value 01111111011111111111111111111111" where the first bit is the sign bit, the next eight bits represent the exponent and everything else the mantissa ?

Kode1000
  • 111
  • 3
  • 4
    The reason you get the message “integer literal is too large to be represented in any integer type” is because the integer literal 340282346638528859811704183484516925440 is too large to be represented in any integer type. – Eric Postpischil Mar 18 '22 at 11:20
  • Re “to convert it to the 32bit value”: To convert something to `float`, you have to have the something first. You have presented the thing as an integer literal, so it has to be interpreted as an integer literal before there is anything to convert to `float`. You can solve this by using a floating-point literal instead of an integer literal, which can be accomplished by putting a `.` at the end of it. Additionally, suffixing `f` would denote it as a `float` literal rather than `double`. – Eric Postpischil Mar 18 '22 at 11:21
  • 2
    Perhaps one of the smallest ever fixes: You just need to add a single character to your code (a dot). – Adrian Mole Mar 18 '22 at 11:21
  • However, note that the C standard’s rules for converting floating-point literals allow some slack, and not all implementations are ideal. You can also obtain the largest finite `float` value by including `` and using `FLT_MAX` or obtain this particular number by using the hexadecimal floating-point format, `0x1.fffffep127f`. – Eric Postpischil Mar 18 '22 at 11:26
  • 1
    @AdrianMole To get the best constant, appending `"."` is not always [sufficient](https://stackoverflow.com/questions/66631288/when-does-appending-an-f-change-the-value-of-a-floating-constant-when-assigned). Better to append a `".f"` (or for esthetics `".0f"`) to avoid double rounding. – chux - Reinstate Monica Mar 18 '22 at 12:52

2 Answers2

4

When 340282346638528859811704183484516925440 appears in source code, without a . or other characters that would modify its type, it is an integer literal, as specified by C 2018 6.4.4.1, which calls it an integer constant. Formally, then, the compiler interprets it as an integer type. The value represented by this numeral is too large to represent in any integer type your compiler supports, so your compiler warns you about it.

The fact the value being assigned to a float is insufficient. The compiler must process the numeral itself before it has a value that it can convert to a float.

The preferred way to get the maximum finite float value is to include <float.h> with an #include directive and use FLT_MAX.

If you want to use the numeral, you can make it a floating-point constant by suffixing .. You can also suffix f to make it a float constant rather than double: 340282346638528859811704183484516925440.f.

The C standard allows some slack in how implementations parse floating-point constants, so it may not be guaranteed that the compiler produces the exact value the numeral represents, even if it is representable in the type. Good C implementations will. However, you can avoid this issue by using the hexadecimal floating-point form, which is guaranteed to produce the correctly rounded result if the C implementation uses a base-two floating-point format. In this form, the number is 0x1.fffffep127f.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
2

As it does not have a decimal point nor an exponent, the number in your program is not parsed as a decimal floating point constant but as an integer constant and it does exceed the maximum value of all integer types available on your system. Your assumption about the compiler behavior is incorrect: the token type is determined from the syntax, not the context. Storing the value of an integer constant to a float involves a conversion to type float, performed at compile time or at run time.

To specify the number as a float constant, add a decimal point and an F suffix at the end:

int main() {
    float biggest = 340282346638528859811704183484516925440.F;
}

If you just write 340282346638528859811704183484516925440. the constant will have type double and will be converted to type float when stored to biggest, which may or may not change the value.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • @EricPostpischil: indeed the grammar in **6.4.4.2 Floating constants** specifies that the *decimal-floating-constant* must have either a *fractional-constant* part and an optional *exponent-part* or a *digit-sequence* and a mandatory *exponent-part*. Since the *floating-suffix* can be `l` or `L`, a alternate rule *digit-sequence floating-suffix* would have been ambiguous. Both **gcc** and **clang** reject `0F` with an error: `invalid suffix "F" on integer constant`. Answer amended. – chqrlie Mar 18 '22 at 12:04