Are there any (valid) C implementations where the float cannot represent the value 0?

If all floats are represented as x = (-1)^s * 2^e * 1.m , it is impossible to keep zero without supporting special cases.

+5
source share
3 answers

No, all relevant C implementations must support a floating point value of 0.0 .

The floating point model is described in section 5.2.4.2.2 of standard C (reference refers to a recent project). This model does not make the leading 1 in the meaningful (sometimes called mantissa) implicit, so it has no problems representing 0.0 .

Most binary floating point implementations do not preserve the leading 1 , but in fact the formula that you indicated in the question:

 x = (-1)^s * 2^e * 1.m 

usually correct (although storage method e may vary).

In such implementations, including IEEE, a special bit-bit is used to represent 0.0 , which is typical for all bit-zero.

Following the discussion in the comments, tmyklebu argues that not all numbers defined by the floating point model in 5.2.4.2.2 must be represented. I disagree; if not all such numbers should be representable, then the model is almost useless. But even leaving this argument aside, there is an explicit requirement that 0.0 must be representable. N1570 6.7.9 clause 10:

If an object that has a static or storage duration of threads is not explicitly initialized, then:

  • ...
  • if it has an arithmetic type, it is initialized to zero (positive or unsigned);
  • ...

This is a very old requirement. A reference C of 1975 (3 years before the publication of K & R1):

The initial value of any external object that is not explicitly initialized is guaranteed to be 0.

which means that there must be a representable value of 0. K & R1 (published in 1978) says, on page 198:

Static and external variables that are not initialized are guaranteed to start at 0; automatic and register variables that are not initialized are guaranteed to start as garbage.

It is interesting to note that the 1990 ISO C standard (equivalent to the 1989 ANSI C standard) is somewhat less explicit than its predecessors and successors. 6.5.7 states:

If an object that has a static storage duration is not initialized explicitly, it is initialized implicitly, as if each member that has an arithmetic type was assigned 0, and each member having a pointer type was assigned a null pointer constant.

If a floating point type is not required for an exact representation for 0.0 , then the phrase "assigned 0" will mean the conversion from int 0 to a floating point type, giving a small value close to 0.0 . However, the C90 has the same floating point model as C99 and C11 (but without mentioning subnormal or abnormal values), and my argument above about model numbers is still applicable. In addition, the C90 standard was officially replaced by the C99, which in turn was replaced by the C11.

+8
source

After searching o, it was found for a while.

ISO / IEC 9899: 201x clause 6.2.5 clause 13

Each complex type has the same presentation and alignment requirements as an array of type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second to the imaginary part of the complex number.

section 6.3.1.7, paragraph 1

When a value of a real type is converted to a complex type, the real part of the complex the value of the result is determined by the rules for converting to the corresponding real type and the imaginary part of the complex value of the result is a positive zero or an unsigned zero.

So, if I understand this right, any implementations that support C99 (the first C standard with _Complex types) should support a floating point value of 0.0.

EDIT Kate Thompson noted that complex types are optional in C99, so this argument is meaningless.

+2
source

I believe the following floating point system is an example of the corresponding floating point arithmetic with no representation for zero:

A float is a 48-bit number with one sign bit, 15 exponent bits, and 32 significant bits. Each selection of a sign bit, an exponent bit, and a significant bit corresponds to a normal floating point number with an estimated leading bit of 1 .

Moving through the limitations in section 5.2.4.2.2, a draft C draft related to Keith Thompson :

  • This floating point system directly corresponds to paragraphs 1 and 2 of section 5.2.4.2.2 in the draft standard.
  • We present only normalized numbers; point 3 just lets us move on.
  • Point 4 is complicated; he says that zero and "values ​​that are not floating point numbers" can be signed or unsigned. But paragraph 3 did not force us to have any values ​​that are not floating point numbers, so I cannot imagine that the interpretation of paragraph 4 requires a null value.
  • The range of values ​​represented in paragraph 5 is apparently -0x1.ffffffffp+16383 - 0x1.ffffffffp+16383 .
  • Clause 6 states that + , - , * , / and the math library have the accuracy determined by the implementation. Still good.
  • Section 7 does not really limit this implementation, so far we can find the corresponding values ​​for all constants.
  • We can set FLT_ROUNDS to 0; thus, I don’t even need to indicate what happens when the addition or subtraction overflows.
  • FLT_EVAL_METHOD must be 0.
  • We have no subnormal numbers, so FLT_HAS_SUBNORM will be null.
  • FLT_RADIX should be 2, FLT_MANT_DIG should be 32, FLT_DECIMAL_DIG should be 10, FLT_DIG should be 9, FLT_MIN_EXP should be -16383, FLT_MIN_10_EXP should be -4933, FLT_MAX_EXP should be 16384, and FLT_MAX_10_EXP .
  • You can work FLT_MAX , FLT_EPSILON , FLT_MIN and FLT_TRUE_MIN .
+1
source

Source: https://habr.com/ru/post/1205646/


All Articles