Is the double 0.0 always represented exactly in portable C?

3.3k views Asked by At

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++?

4

There are 4 answers

7
Stephen Canon On BEST ANSWER

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.

0
Pascal Cuoq On

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.

1
Mark Ransom On

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.

5
caf On

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.