Re: C2124 is most disrespectful of IEEE floating point arithmetic

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



In the standard:

"If during the evaluation of an expression, the result is not mathematically
defined or not in the range of representable
values for its type, the behavior is undefined, unless such an expression is
a constant expression
(5.19), in which case the program is illformed.
[Note: most existing implementations of C++ ignore integer
overflows. Treatment of division by zero, forming a remainder using a zero
divisor, and all floating
point exceptions vary among machines, and is usually adjustable by a library
function. ]"

Clause 5.119.3:
An arithmetic constant expression shall have arithmetic or enumeration type
and shall only have operands
that are integer literals (2.13.1), floating literals (2.13.3), enumerators,
character literals (2.13.2) and
sizeof expressions (5.3.3). Cast operators in an arithmetic constant
expression shall only convert arithmetic
or enumeration types to arithmetic or enumeration types, except as part of
an operand to the sizeof
operator.

This means: 1.f/0.f is a constant expression and the compiler is evaluating
it on compile time. Since it's not _mathematically_ defined (don't mind it's
defined by IEC559), the program is illformed.

const float zero = 0.;
float inf = 1. / zero; // not a constant expression, contains non-integer
variables (even though const).

Note that const variables form a integer constant expression only if they
are int or enum. See 5.19.1.


"Dr Pizza" <DrPizza@xxxxxxxxxxxxxxxxx> wrote in message
news:xn0eqilnkvflvg002@xxxxxxxxxxxxxxxxxxxxxxx
Doug Harrison [MVP] wrote:

On Sun, 27 Aug 2006 17:51:26 -0700, "Dr Pizza"
<DrPizza@xxxxxxxxxxxxxxxxx> wrote:

Since VC++ purports to follow IEC 559, and IEC 559 defines the
division of a non-zero by a zero to be a signed infinity, isn't it
rather silly that:

float inf(1.0f / 0.0f);

should result in a compile-time error, C2124? An error may be
appropriate for integer arithmetic (as it'll generate a runtime SEH
exception), but for floating point arithmetic it's surely incorrect
behaviour?

What gives? Am I being unreasonable in my expectations? It's
certainly rather nicer to type the above than have to spew:

float inf(std::numeric_limits<float>::infinity());

Division by zero is undefined, so the compiler can do whatever it
wants. For a compile-time expression, emitting an error is highly
appropriate. Using numeric_limits as above is self-documenting and
portable, and it is highly preferable to 1.0/0.0.

But it isn't undefined. Well; it's undefined in standard mathematics.
It isn't undefined in IEC 559, and VC++ purports to adhere to IEC 559.

IEEE 754 says that in the case of division of a finite value by zero:
<quotation>
7.2 Division by Zero

If the divisor is zero and the dividend is a finite nonzero number,
then the division by zero exception shall be signaled. The result, when
no trap occurs, shall be a correctly signed [Infinity] (6.3).
</quotation>

So depending on our handling of FP exceptions we should see one of two
things: with exceptions disabled, a signed infinity; with exceptions
enabled a divide by zero exception.

Yet in this case we get neither a trap nor a correctly signed infinity.
Instead, we have a compile-time error.

This is in spite of std::numeric_limits<float>::is_iec559 being 'true'
for float.

I don't see how you can have it both ways. Either is_iec559 should be
'false'--in which case all bets are off as to the behaviour of these
types and they are indeed "undefined", and a compile-time error is
consistent (even if not at all useful)--or the compiler should refrain
from trapping the division at compile-time, and instead allow the
defined runtime behaviour to occur.

I don't see why using numeric_limits is "highly preferable", as 1.0/0.0
is concise, well-defined, and clear.

--



.



Relevant Pages

  • Re: C2124 is most disrespectful of IEEE floating point arithmetic
    ... This is a compile-time constant expression, ... of a non-zero by a zero to be a signed infinity, ... should result in a compile-time error, ...
    (microsoft.public.vc.language)
  • Re: So whats null then if its not nothing?
    ... The NULL propagation is simple - NULLS in, NULLS out, ... Allowing exceptions means that there will be ... But NULL*0 not being zero is also doing that. ...
    (comp.databases.theory)
  • Re: T edit descriptor and ADVANCE="NO"
    ... Advancing I/O terminates a record. ... a formatted record may have zero length. ... I don't see any exceptions for zero-length mentioned in the bit about ...
    (comp.lang.fortran)
  • Re: Division by zero
    ... > B/A is a static expression, which has to have a value at compile-time. ... >> reason) to zero. ... > compile time cannot be compile-time errors. ... that was split into "divide by zero in a static expression" ...
    (comp.lang.ada)
  • Re: C2124 is most disrespectful of IEEE floating point arithmetic
    ... Division by zero is undefined, so the compiler can do whatever it ... For a compile-time expression, ... then the division by zero exception shall be signaled. ... a signed infinity; ...
    (microsoft.public.vc.language)