3

Can the following code be expected to work in all environments that have an ANSI-compliant C compiler?

double n = 0;
assert(n == 0);

What about C++?

kirakun
  • 2,770
  • 1
  • 25
  • 41

4 Answers4

6

The C standard does put some limitations on how floating point values are represented. In §5.2.4.2.2 Characteristics of floating types, floating point numbers must exhibit characteristics as if they were defined by the model:

x = sbe Σk=1..p fk b-k

Where:

  • s is the sign, and must be ±1;
  • b is the base, and must be an integer > 1;
  • e is the exponent and must be an integer between emin and emax;
  • p is the precision; and
  • fk are non-negative integers < b - the digits of the significand.

Under this model, zero is always able to be exactly represented - it simply requires all the significand digits fk to be zero.

Given the following restriction in §6.3.1.4:

When a value of integer type is converted to a real floating type, if the value being converted can be represented exactly in the new type, it is unchanged.

It follows that zero must always be unchanged when converted from the integer 0 to a floating point type. Therefore the assertion must always hold.

caf
  • 233,326
  • 40
  • 323
  • 462
  • A few problems: a narrow reading of the actual text does not indicate that there must be a representation of zero; rather, it only requires that zero is represented by a significand of zero. More to the point, take special note of footnote (16): "The floating-point model is intended to clarify the description of each floating-point characteristic and does not require the floating-point arithmetic of the implementation to be identical." – Stephen Canon Apr 15 '11 at 02:11
  • However, as I indicated in my answer and comments, I do not know of any floating-point implementation that does not provide a representation of zero, so this is really a hypothetical corner case of a corner case, and will never occur in the real world. Indeed, this situation would be so perverse that I believe that the C committee did not even consider it, which is (I assume) why the standard does not explicitly contain language requiring a representation of zero. – Stephen Canon Apr 15 '11 at 02:12
  • @Stephen Canon: The standard does require that the implementation *act like* such a model - a reading that implies otherwise would mean that the entire floating point characteristics chapter is meaningless. Values such as `FLT_RADIX` only have meaning in relation to the model. Note also that the description of `DBL_MAX_EXP` also implies that 0 must be representable, since 0 is an integer less than any `FLT_RADIX` raised to any power. – caf Apr 15 '11 at 02:24
  • the definition of `DBL_MAX_EXP` only requires that some exact power of two be representable, not that zero be. – Stephen Canon Apr 15 '11 at 16:17
  • @Stephen Canon: Perhaps. I think we will simply have to agree to disagree on this matter - as far as I see it, 0.0 is representable by definition, since it is always representable in the given floating point model no matter what the parameters chosen. – caf Apr 16 '11 at 02:43
5

You're not asking if 0.0 is always represented exactly.

In the statement assert(n == 0), 0 is converted to double before the comparison occurs. Thus, the assert can only be triggered if converting 0 from int to double is not reproducible. This is a much weaker restriction than what you're asking about, and will almost certainly hold (though I can't think of a standards reference to guarantee it off the top of my head).

To the question you intended to ask:

As others mentioned, the C standard does not require that floating-point types map to IEEE-754, but I am not aware of any floating-point representation used with any C compiler that does not have an exact representation of zero. That said, it would be "legal" for a C implementation to use a format for double that did not have an exact zero.

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
  • Mark's unimaginative answer seems to call for your wisdom... ;-) – R.. GitHub STOP HELPING ICE Apr 14 '11 at 22:13
  • What variants of floating point are used on mobile devices? Until recently the desktop has been the major playground for most amateur /semi-professional developers but with mobile devices becoming exceedingly popular they are becoming the major development platform and as such we need to consider floating point representations on these devices. What is your confidence level of 754 support on mobile devices? – Martin York Apr 14 '11 at 22:15
  • @Martin: You may note that my answer is not contingent on IEEE-754 support. That said, the iPhone has nearly-754 semantics (the default floating-point environment flushes denormals to zero, but it conforms otherwise). I believe that Android also has mostly-754 arithmetic (inherited from Java). I'm not certain about other platforms. I do believe that all floating-point formats in use on mainstream mobile devices have an exact representation of zero, however. – Stephen Canon Apr 14 '11 at 22:18
  • Is it really just a case of reproducibility, though? It's possible that in one case `0` is converted to double, but in the other case it's converted to double, *stored in memory* and then retrieved. I think it's legal for C and C++ implementations to reduce precision when storing to memory, isn't it? In which case in the hypothetical situation of `0` not having a precise representation, can't `n` be not equal to `(double)0` because of that? – Steve Jessop Apr 14 '11 at 22:44
  • Or is it only intermediate arithmetic results which can have greater precision than the stored values, not "brand new" doubles resulting from a cast? Or have I imagined the whole thing, and that old behavior typical on x87, of not rounding intermediate values to 64 bits, never conformed to the C or C++ standards? – Steve Jessop Apr 14 '11 at 22:46
  • @Steve Jessop: No, I believe there are all sorts of nefarious things that a malicious implementation that didn't have an exact representation of zero in double could do. It's just that (a) compiler writers are not--in general--malicious and (b) I do not know of **any** C environment in which zero is not represented exactly in double precision. – Stephen Canon Apr 14 '11 at 23:05
  • I do not believe a conforming C implementation can use floating point types where zero is not exactly representable - see my answer. – caf Apr 15 '11 at 00:45
2

The comparison will promote the integer to a double. What you're asking is if the compiler is guaranteed to do identical conversions each time it converts identical integers to double. I believe it is.

Not only that, any small enough integer can be exactly represented by a double. I can't imagine any compiler that would do a conversion in that case that wasn't precise.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • I'm reasonably certain that a malicious implementation could have a double type without an exact representation of zero, choose between the two closest values based on the low bit of RTSC, and claim conformance to the standard. This would be truly evil, however. – Stephen Canon Apr 14 '11 at 22:18
1

C99 does not mandate IEEE754, only recommends it. There is a symbol that IEEE 754 compliant compilation platforms can define (Annex F). If the compiler defines this symbol, then yes, the assertion would be guaranteed to hold. When the literal constant is representable exactly as a floating-point number, then this floating-point number is what you must get in the compiled program.

I cannot think of any non-IEEE 754 floating-point system that wouldn't have a zero, or a reason not to map the literal 0 in the source code to it.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281