13

I want to define the result of division by zero as the double INF.

There are some discussions about the default behavior in C/C++ for division by zero. No question (that I read) asks explicitly how to define the division by zero to become infinity in C. Whether this makes sense or not I would rather not discuss. I just want to define it that way for one file with several C functions in it and need the syntax for it.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
hcl734
  • 372
  • 1
  • 10
  • 2
    On the surface it doesn't sound possible, but it may depend on the level of control you have. For example: can you replace all division operations with a function call? In short - What have you tried? :) – Aviv Goll Jun 18 '19 at 08:23
  • 6
    a floating point division by zero already results in `INF`. If you want to define it the same way for integers, you must break the standard, because an integer division results in an integer, which cannot represents `INF`. – mch Jun 18 '19 at 08:32
  • It's probably easier to handle for integer division by catching a zero divisor *before* the division. The alternative is to set up a recovery mechanism. – Weather Vane Jun 18 '19 at 08:38
  • 1
    If code trying to avoid `-1.0/0.0` as `-INF`? Sounds like you want that to be `+INF` too. – chux - Reinstate Monica Jun 18 '19 at 10:14

2 Answers2

13

If you require this behaviour, use floating point numbers, which can represent infinity, and provide the desired behaviour. Note that technically this is undefined behaviour but in practice most compilers (all mainstream compilers for standard architectures) implement IEEE 754 semantics, e.g. GCC.

int main() {
    float f = 42;
    float g = f / 0.0f;
    printf("%f\n", g);
}

Output:

inf

This is behaviour that can be relied on since it’s clearly documented by the compilers. However, when writing portable code make sure that you test these assumptions inside your code (e.g. by testing whether the preprocessor macro __STDC_IEC_559__, as well as compiler-specific macros are defined).

If, for some reason, you need this behaviour for integer values, the only recourse is to make your own type. Something like this:

typedef struct {
    int value;
    bool is_inf;
    bool is_nan;
} ext_int;

ext_int make_ext_int(int i) {
    return (ext_int) {i, false, false};
}

ext_int make_nan() {
    return (ext_int) {0, false, true};
}

ext_int make_inf(int sign) {
    return (ext_int) {(sign > 0) - (sign < 0), true, false};
}

ext_int ext_div(ext_int a, ext_int b) {
    if (a.is_nan || b.is_nan) {
        return  make_nan();
    }
    if (b.value == 0) {
        return make_inf(a.value);
    }
    // TODO: insert other cases.
    return (ext_int) {a.value / b.value, false, false};
}

… in a real implementation you’d pack the different flags rather than having a separate bool for each, of course.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 1
    Floating point division by zero is still undefined behaviour by the standard, although IEEE754 does define it the way you have for a positive numerator. – Bathsheba Jun 18 '19 at 08:40
  • `if (b.is_nan || b.is_inf) { return make_nan();` looks wrong. Did your want `if (a.is_nan || b.is_nan) { ...`? Code needs more cases too. Is UB for `a=INT_MIN, b = -1` ... – chux - Reinstate Monica Jun 18 '19 at 10:16
  • @chux This was a very quick write-up with limited testing. The purpose is explicitly *not* production code (which would be way too long) but rather an illustration. That said, the intention of the conditional was to ensure that `x / inf` returns `NaN`. And you’re right, that’s wrong. – Konrad Rudolph Jun 18 '19 at 10:25
  • 1
    Depending on the needs, you don't necessarily need your own new struct, just custom functions. `INT_MIN` and `INT_MAX` are comparatively rarely used; it wouldn't be unreasonable to say "alright, those are infinity now". – Nic Jun 18 '19 at 18:32
  • Out of curiosity, can you think of *any* compiler which has a floating point value for infinity, but does not evaluate 1./0. as infinity? While it's officially UB, it seems like the presence of an infinity value strongly implies 1/0=inf. – Cort Ammon Jun 18 '19 at 21:10
  • @CortAmmon It's not so much about the compiler as it is about the architecture. The compiler takes advantage of the UB to just use normal floating-point division, without worrying about whether it interrupts, sets infinity, sets NaN, or whatever -- it's UB. It can do whatever. It gives them the option to save a few clock cycles in more esoteric ways, too. – Nic Jun 29 '19 at 20:55
8

Floating point division by zero is undefined by the C standard.

(IEEE754 - common but by no means ubiquitous - defines a / 0.0 to be +INF if a is positive, -INF if a is negative and NaN if a is also zero).

Your best bet is to define a function that models the division operator, and implement your behaviour there.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483