A few things about division by zero in C [duplicate] - c++

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Value returning 1.#INF000
I always thought division by 0 would result in a compiled program crashing
However I discovered today (using VC++ 2010 Express) that division by 0 gives something called 1.#INF000 and it is supposed to be positive infinity
When it was passed to a function, it got passed as -1.#IND000
What is this all about?
Searching 1.#INF000 and -1.#IND000 on google do not provide any clear explanations either
Is it just something specific to VC++ ?

Floating point division by zero behaves differently than integer division by zero.
The IEEE floating point standard differentiates between +inf and -inf, while integers cannot store infinity. Integer division by zero results in undefined behaviour. Floating point division by zero is defined by the floating point standard and results in +inf or -inf.
Edit:
As pointed out by Luchian, C++ implementations are not required to follow the IEEE Floating point standard. If the implementation you use doesn't follow the IEEE Floating point standard the result of floating point division by zero is undefined.

Edit: The question is about C++ and the result in C++ is undefined, as clearly stated by the standard, not the IEEE or whatever other entity that doesn't, in fact, regulate the C++ language. The standard does. C++ implementations might follow IEEE rules, but in this case it's clear the behavior is undefined.
I always thought division by 0 would result in a compiled program crashing
Nope, it results in undefined behavior. Anything can happen, a crash is not guaranteed.
According to the C++ Standard:
5.6 Multiplicative operators
4) The binary / operator yields the quotient, and the binary %
operator yields the remainder from the division of the first
expression by the second. If the second operand of / or % is zero the behavior is undefined; otherwise (a/b)*b + a%b
is equal to a. If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is
implementation-defined79). (emphasis mine)

Quoting the latest draft of the ISO C++ standard, section 5.6 ([expr.mul]):
If the second operand of / or % is zero the behavior is undefined.
This applies to both integer and floating-point division.
A particular C++ implementation may conform to the IEEE floating-point standard, which has more specific requirements for division by zero, which which case the behavior may be well defined for that implementation. That's probably why floating-point division by zero yields Infinity in your implementation. But the C++ standard doesn't require IEEE floating-point behavior.

you can use the following code sniplet in C.
it throws the exception. it works on linux donno about windows though
#include <fenv.h>
#include <TRandom.h>
static void __attribute__ ((constructor)) trapfpe(void)
{
/* Enable some exceptions. At startup all exceptions are masked. */
feenableexcept(FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW);
}

Related

The behaviour of floating point division by zero

Consider
#include <iostream>
int main()
{
double a = 1.0 / 0;
double b = -1.0 / 0;
double c = 0.0 / 0;
std::cout << a << b << c; // to stop compilers from optimising out the code.
}
I have always thought that a will be +Inf, b will be -Inf, and c will be NaN. But I also hear rumours that strictly speaking the behaviour of floating point division by zero is undefined and therefore the above code cannot considered to be portable C++. (That theoretically obliterates the integrity of my million line plus code stack. Oops.)
Who's correct?
Note I'm happy with implementation defined, but I'm talking about cat-eating, demon-sneezing undefined behaviour here.
C++ standard does not force the IEEE 754 standard, because that depends mostly on hardware architecture.
If the hardware/compiler implement correctly the IEEE 754 standard, the division will provide the expected INF, -INF and NaN, otherwise... it depends.
Undefined means, the compiler implementation decides, and there are many variables to that like the hardware architecture, code generation efficiency, compiler developer laziness, etc..
Source:
The C++ standard state that a division by 0.0 is undefined
C++ Standard 5.6.4
... If the second operand of / or % is zero the behavior is undefined
C++ Standard 18.3.2.4
...static constexpr bool is_iec559;
...56. True if and only if the type adheres to IEC 559 standard.217
...57. Meaningful for all floating point types.
C++ detection of IEEE754:
The standard library includes a template to detect if IEEE754 is supported or not:
static constexpr bool is_iec559;
#include <numeric>
bool isFloatIeee754 = std::numeric_limits<float>::is_iec559();
What if IEEE754 is not supported?
It depends, usually a division by 0 trigger a hardware exception and make the application terminate.
Quoting cppreference:
If the second operand is zero, the behavior is undefined, except that if floating-point division is taking place and the type supports IEEE floating-point arithmetic (see std::numeric_limits::is_iec559), then:
if one operand is NaN, the result is NaN
dividing a non-zero number by ±0.0 gives the correctly-signed infinity and FE_DIVBYZERO is raised
dividing 0.0 by 0.0 gives NaN and FE_INVALID is raised
We are talking about floating-point division here, so it is actually implementation-defined whether double division by zero is undefined.
If std::numeric_limits<double>::is_iec559 is true, and it is "usually true", then the behaviour is well-defined and produces the expected results.
A pretty safe bet would be to plop down a:
static_assert(std::numeric_limits<double>::is_iec559, "Please use IEEE754, you weirdo");
... near your code.
Division by zero both integer and floating point are undefined behavior [expr.mul]p4:
The binary / operator yields the quotient, and the binary % operator yields the remainder from the division
of the first expression by the second. If the second operand of / or % is zero the behavior is undefined. ...
Although implementation can optionally support Annex F which has well defined semantics for floating point division by zero.
We can see from this clang bug report clang sanitizer regards IEC 60559 floating-point division by zero as undefined that even though the macro __STDC_IEC_559__ is defined, it is being defined by the system headers and at least for clang does not support Annex F and so for clang remains undefined behavior:
Annex F of the C standard (IEC 60559 / IEEE 754 support) defines the
floating-point division by zero, but clang (3.3 and 3.4 Debian snapshot)
regards it as undefined. This is incorrect:
Support for Annex F is optional, and we do not support it.
#if STDC_IEC_559
This macro is being defined by your system headers, not by us; this is
a bug in your system headers. (FWIW, GCC does not fully support Annex
F either, IIRC, so it's not even a Clang-specific bug.)
That bug report and two other bug reports UBSan: Floating point division by zero is not undefined and clang should support Annex F of ISO C (IEC 60559 / IEEE 754) indicate that gcc is conforming to Annex F with respect to floating point divide by zero.
Though I agree that it isn't up to the C library to define STDC_IEC_559 unconditionally, the problem is specific to clang. GCC does not fully support Annex F, but at least its intent is to support it by default and the division is well-defined with it if the rounding mode isn't changed. Nowadays not supporting IEEE 754 (at least the basic features like the handling of division by zero) is regarded as bad behavior.
This is further support by the gcc Semantics of Floating Point Math in GCC wiki which indicates that -fno-signaling-nans is the default which agrees with the gcc optimizations options documentation which says:
The default is -fno-signaling-nans.
Interesting to note that UBSan for clang defaults to including float-divide-by-zero under -fsanitize=undefined while gcc does not:
Detect floating-point division by zero. Unlike other similar options, -fsanitize=float-divide-by-zero is not enabled by -fsanitize=undefined, since floating-point division by zero can be a legitimate way of obtaining infinities and NaNs.
See it live for clang and live for gcc.
Division by 0 is undefined behavior.
From section 5.6 of the C++ standard (C++11):
The binary / operator yields the quotient, and the binary % operator
yields the remainder from the division of the first expression by the
second. If the second operand of / or % is zero the behavior is
undefined. For integral operands the / operator yields the algebraic
quotient with any fractional part discarded; if the quotient a/b is
representable in the type of the result, (a/b)*b + a%b is equal to a .
No distinction is made between integer and floating point operands for the / operator. The standard only states that dividing by zero is undefined without regard to the operands.
In [expr]/4 we have
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. [ 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. —end note ]
Emphasis mine
So per the standard this is undefined behavior. It does go on to say that some of these cases are actually handled by the implementation and are configurable. So it won't say it is implementation defined but it does let you know that implementations do define some of this behavior.
As to the submitter's question 'Who's correct?', it is perfectly OK to say that both answers are correct. The fact that the C standard describes the behavior as 'undefined' DOES NOT dictate what the underlying hardware actually does; it merely means that if you want your program to be meaningful according to the standard you -may not assume- that the hardware actually implements that operation. But if you happen to be running on hardware that implements the IEEE standard, you will find the operation is in fact implemented, with the results as stipulated by the IEEE standard.
This also depends on the floating point environment.
cppreference has details:
http://en.cppreference.com/w/cpp/numeric/fenv
(no examples though).
This should be available in most desktop/server C++11 and C99 environments. There are also platform-specific variations that predate the standardization of all this.
I would expect that enabling exceptions makes the code run more slowly, so probably for this reason most platforms that I know of disable exceptions by default.

Is maximum float + x defined behavior?

I did a quick test using the following:
float x = std::numeric_limits<float>::max();
x += 0.1;
that resulted in x == std::numeric_limits::max() so it didn't get any bigger than the limit.
Is this guaranteed behavior across compilers and platforms though? What about HLSL?
Is this guaranteed behavior across compilers and platforms though?
No, the behavior is undefined. The standard says (emphasis mine):
5 Expressions....
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. [ 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. —end note ]
As #user2079303 mentioned, in practice we can be less restricted:
it is not undefined if std::numeric_limits<float>::has_infinity. Which is often true. In that case, the result is merely unspecified.
The value of std::numeric_limits<T>::max() is defined to be the maximum finite value representable by type T (see 18.3.2.4 [numeric.limits.members] paragraph 4). Thus, the question actually becomes multiple subquestions:
Is it possible to create a value bigger than std::numeric_limits<T>::max(), i.e., is there an infinity?
If so, which value needs to be added to std::numeric_limits<T>::max() to get the infinity?
If not, is the behavior defined?
C++ does not specify the floating point format and different formats may disagree on what the result is. In particular, I don't think floating point formats need to define a value for infinity. For example, IBM Floating Points do not have an infinity. On the other hand the IEEE 754 does have an infinity representation.
Since overflow of arithmetic types may be undefined behavior (see 5 [expr] paragraph 4) and I don't see any exclusion for floating point types. Thus, the behavior would be undefined behavior if there is no infinity. At least, it can be tested whether a type does have an infinity (see 18.3.2.3 [numeric.limits] paragraph 35) in which case the operation can't overflow.
If there is an infinity I think adding any value to std::numeric_limits<T>::max() would get you infinity. However, determining whether that is, indeed, the case would require to dig through the respective floating point specification. I could imagine that IEEE 754 might ignore additions if the value is too small to be relevant as is the case for adding 0.1 to std::numeric_limits<T>::max(). I could also imagine that it decides that it always overflows to infinity.

should ldexp round correctly

I'm a bit surprised with MSVC ldexp behavior (it happens in Visual Studio 2013, but also with all older versions at least down to 2003...).
For example:
#include <math.h>
#include <stdio.h>
int main()
{
double g=ldexp(2.75,-1074);
double e=ldexp(3.0,-1074);
printf("g=%g e=%g \n",g,e);
return 0;
}
prints
g=9.88131e-324 e=1.4822e-323
The first one g is strangely rounded...
It is 2.75 * fmin_denormalized, so i definitely expect the second result e.
If I evaluate 2.75*ldexp(1.0,-1074) I correctly get same value as e.
Are my expectations too high, or does Microsoft fail to comply with some standard?
While the question does not explicitly state this, I assume that the output expected by the asker is:
g=1.4822e-323 e=1.4822e-323
This is what we would expect from a C/C++ compiler that promises strict adherence to IEEE-754. The question is tagged both C and C++, I will address C99 here as that is the standard I have in hand.
In Annex F, which describes IEC 60559 floating-point arithmetic (where IEC 60559 is basically another name for IEEE-754) the C99 standard specifies:
An implementation that defines __STDC_IEC_559__ shall conform to the
specifications in this annex. [...] The scalbn and scalbln
functions in <math.h> provide the scalb function recommended in the
Appendix to IEC 60559.
Further down in that annex, section F.9.3.6 specifies:
On a binary system, ldexp(x, exp) is equivalent to scalbn(x, exp).
The appendix referenced by the C99 standard is the appendix of the 1985 version of IEEE-754, where we find the scalb function defined as follows:
Scalb(y, N) returns y × 2N for integral values N without computing 2N.
scalb is defined as a multiplication with a power of two, and multiplications must be rounded correctly based on the current rounding mode according to the standard. Therefore, with a conforming C99 compiler ldexp() must return a correctly rounded result if the compiler defines __STDC_IEC_559__. In the absence of a library call setting the rounding mode, the default rounding mode "round to nearest or even" is in effect.
I do not have access to MSVC 2013, so I do not know whether it defines that symbol or not. This could even depend on a compiler flag setting, such as /fp:strict.
After tracking down my copy of the C++11 standard, I cannot find any reference to __STDC_IEC_559__ or any language about IEEE-754 bindings. According to the answer to this question this is because that support is included by referring to the C99 standard.
This happens because during the ldexp calculation the 2.75 gets truncated to 2, which happens because at that small of a denormalized number the bits that represent the '.75' part get shifted off the end of the representable number and disappear. Whether this is a bug or designed behavior can be debated.
When calculating 2.75*ldexp(1.0,-1074) normal rounding happens, and the 2.75 becomes 3.
EDIT: ldexp should round correctly, and this is a bug.
OP results do not fail to comply with the C spec as that spec does not define the preciseness of calculations.
OP result may have failed IEEE 754, but it depends on the rounding mode in use at the time, which is not posted. Yet OP's reports 2.75*ldexp(1.0,-1074) worked as expected implying at that time, the expected rounding mode was in effect.
Using printf("%la",x) aids in seeing clearly what is happening near the limits of double.
I would expect g to "round to nearest - ties to even" with the result of 0x1.8p-1073 - which did occur with gcc on windows.
Ideally g would have the value of 0x1.6p-1073
0x0.0p-1073 Zero
0x0.8p-1073 next higher double DBL_TRUE_MIN
0x1.0p-1073 next higher double
0x1.6p-1073 ideal `g` answer, but not available as a double
0x1.8p-1073 next higher double
To be fair, it could be a processor bug - it has happened before.
Ref
double g=ldexp(2.75,-1074);
printf("%la\n%la\n", 2.75,ldexp(2.75,-1074));
printf("%la\n%la\n", 3.0 ,ldexp(3.0 ,-1074));
double e=ldexp(3.0,-1074);
printf("%la\n%la\n", g,e);
printf("%la\n%la\n", 9.88131e-324, DBL_TRUE_MIN);
printf("g=%g e=%g \n",g,e);
0x1.6p+1
0x1.8p-1073
0x1.8p+1
0x1.8p-1073
0x1.8p-1073
0x1.8p-1073
0x1p-1073
0x1p-1074
g=1.4822e-323 e=1.4822e-323

Division by zero: Undefined Behavior or Implementation Defined in C and/or C++?

Regarding division by zero, the standards say:
C99 6.5.5p5 - The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined.
C++03 5.6.4 - The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined.
If we were to take the above paragraphs at face value, the answer is clearly Undefined Behavior for both languages. However, if we look further down in the C99 standard we see the following paragraph which appears to be contradictory(1):
C99 7.12p4 - The macro INFINITY expands to a constant expression of type float representing positive or unsigned infinity, if available;
Do the standards have some sort of golden rule where Undefined Behavior cannot be superseded by a (potentially) contradictory statement? Barring that, I don't think it's unreasonable to conclude that if your implementation defines the INFINITY macro, division by zero is defined to be such. However, if your implementation does not define such a macro, the behavior is Undefined.
I'm curious what the consensus is (if any) on this matter for each of the two languages. Would the answer change if we are talking about integer division int i = 1 / 0 versus floating point division float i = 1.0 / 0.0 ?
Note (1) The C++03 standard talks about the <cmath> library which includes the INFINITY macro.
I don't see any contradiction. Division by zero is undefined, period. There is no mention of "... unless INFINITY is defined" anywhere in the quoted text.
Note that nowhere in mathematics it is defined that 1 / 0 = infinity. One might interpret it that way, but it is a personal, "shortcut" style interpretation, rather than a sound fact.
1 / 0 is not infinity, only lim 1/x = ∞ (x -> +0)
This was not a math purest question, but a C/C++ question.
According to the IEEE 754 Standard, which all modern C compilers / FPU's use, we have
3.0 / 0.0 = INF
0.0 / 0.0 = NaN
-3.0 / 0.0 = -INF
The FPU will have a status flag that you can set to generate an exception if so desired, but this is not the norm.
INF can be quite useful to avoiding branching when INF is a useful result. See discussion here
http://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF
Why would it?
That doesn't make sense mathematically, it's not as if 1/x is defined as ∞ in mathematics in general. Also, you would at least need two more cases: -1/x and 0/x can't also equal ∞.
See division by zero in general, and the section about computer arithmetic in particular.
Implementations which define __STDC_IEC_559__ are required to abide by the requirements given in Annex F, which in turn requires floating-point semantics consistent with IEC 60559. The Standard imposes no requirements on the behavior of floating-point division by zero on implementations which do not define __STDC_IEC_559__, but does for those which do define it. In cases where IEC 60559 specifies a behavior but the C Standard does not, a compiler which defines __STDC_IEC_559__ is required by the C Standard to behave as described in the IEC standard.
As defined by IEC 60559 (or the US standard IEEE-754) Division of zero by zero yields NaN, division of a floating-point number by positive zero or literal constant zero yields an INF value with the same sign as the dividend, and division of a floating-point number by negative zero yields an INF with the opposite sign.
I've only got the C99 draft. In §7.12/4 it says:
The macro
INFINITY
expands to a constant expression of
type float representing positive or
unsigned infinity, if available; else
to a positive constant of type float
that overflows at translation time.
Note that INFINITY can be defined in terms of floating-point overflow, not necessarily divide-by-zero.
For the INFINITY macro: there is a explicit coding to represent +/- infinity in the IEEE754 standard, which is if all exponent bits are set and all fraction bits are cleared (if a fraction bit is set, it represents NaN)
With my compiler, (int) INFINITY == -2147483648, so an expression that evaluates to int i = 1/0 would definitely produce wrong results if INFINITIY was returned
Bottom line, C99 (as per your quotes) does not say anything about INFINITY in the context of "implementation-defined". Secondly, what you quoted does not show inconsistent meaning of "undefined behavior".
[Quoting Wikipedia's Undefined Behavior page] "In C and C++, implementation-defined behavior is also used, where the language standard does not specify the behavior, but the implementation must choose a behavior and needs to document and observe the rules it chose."
More precisely, the standard means "implementation-defined" (I think only) when it uses those words with respect to the statement made since "implementation-defined" is a specific attribute of the standard. The quote of C99 7.12p4 didn't mention "implementation-defined".
[From C99 std (late draft)] "undefined behavior: behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements"
Note there is "no requirement" imposed for undefined behavior!
[C99 ..] "implementation-defined behavior: unspecified behavior where each implementation documents how the choice is made"
[C99 ..] "unspecified behavior: use of an unspecified value, or other behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance"
Documentation is a requirement for implementation-defined behavior.

Integer division rounding with negatives in C++

Suppose a and b are both of type int, and b is nonzero. Consider the result of performing a/b in the following cases:
a and b are both nonnegative.
a and b are both negative.
Exactly one of them is negative.
In Case 1 the result is rounded down to the nearest integer. But what does the standard say about Cases 2 and 3? An old draft I found floating on the Internet indicates that it is implementation dependent (yes, even case 2) but the committee is leaning toward making it always 'round toward zero.' Does anyone know what the (latest) standard says? Please answer only based on the standard, not what makes sense, or what particular compilers do.
As an update to the other answers:
The last draft of C++11, n3242 which is for most practical purposes identical to the actual C++11 standard, says this in 5.6 point 4 (page 118):
For integral operands the / operator yields the algebraic quotient
with any fractional part discarded; (see note 80)
Note 80 states (note that notes are non-normative):
80) This is often called truncation towards zero.
Point 4 goes on to state:
if the quotient a/b is representable in the type of the result,
(a/b)*b + a%b is equal to a.
which can be shown to require the sign of a%b to be the same as the sign of a (when not zero).
According to the May 2008 revision,
You're right:
The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined; otherwise (a/b)*b + a%b is equal to a. If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined75).
Note 75 says:
According to work underway toward the revision of ISO C, the preferred algorithm for integer division follows the rules defined in the ISO Fortran standard, ISO/IEC 1539:1991, in which the quotient is always rounded toward zero.
Chances are that C++ will lag C in this respect. As it stands, it's undefined but they have an eye towards changing it.
I work in the same department as Stroustrup and with a member of the committee. Things take AGES to get accomplished, and its endlessly political. If it seems silly, it probably is.
Just a comment. The current working draft for the C++ standard indeed corrects the "implementation-defined" issue and asks for truncation towards zero. Here is the committee's webpage, and here is the draft. The issue is at page 112.
Sometimes we need to take a step back, and look just at the mathematics of it:
Given int x, int y
if int i1 = x/y and
int i2 = x%y
then y * i1 + i2 must be x
So this is not so much about the standard, but there is only one way this can possibly be. If any standards allows it to be any other way, then the standard is wrong, and that means the language is broken.