I know that modern languages handle integer divide by zero as an error just like the hardware does, but what if we could design a whole new language?

Ignoring existing hardware, what should a programming language does when an integer divide by zero occurs? Should it return a NaN of type integer? Or should it mirror IEEE 754 float and return +/- Infinity? Or is the existing design choice correct, and an error should be thrown?

Is there a language that handles integer divide by zero nicely?

EDIT
When I said ignore existing hardware, I mean don't assume integer is represented as 32 bits, it can be represented in anyway you can to imagine.

This question came from our site for professional and enthusiast programmers. Votes, comments, and answers are locked due to the question being closed here, but it may be eligible for editing and reopening on the site where it originated.

There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.
If this question can be reworded to fit the rules in the help center, please edit the question.

It seems that what you want is a compiler/language that will by default ignore your programming and logic errors! If you divide by zero you have made a mistake, it may be a design error or just a typo perhaps just insufficient validation -- but you have made a mistake.
–
James AndersonNov 16 '11 at 3:02

Its very domain dependent. Some domains this should error, some you should get 0, some you should get NaN, and some you should get some Infinity value. A DSL may have different needs than a general programming language.
–
RigOct 9 '13 at 16:51

13 Answers
13

Usually, integer types of programming languages do not support NaN values. Since they use the whole, say, 32 bits for storing the number without any special values. IEEE754 defines special bit patterns for +Inf, -Inf, Nan, ... which are not defined for an int.

Personally, I believe the way it's handled by throwing a DivideByZeroException is pretty good. If you reach a point that you hadn't checked for divide by zero, you've probably missed something you shouldn't have ignored, therefore, it's critical to issue a fatal error.

EDIT: Ignoring the way hardware handles integers, I still believe the error should be in form of an exception or something, at least by default. The primary reason doubles allow divide by zero is the fact that due to a computation, you might have a very small value near to zero to divide by. In fact, +Infinity does not mean real infinity. It means it's much larger than can be handled by a double. For an int, the range is much limited and the closest positive value to 0 is 1, so divide by zero in an int is most likely a programming error as opposed to a precision loss.

Agree with this 100%. A division op is math, and in math dividing by 0 is undefined. It's not legal, it's not allowed, and it's not infinite unless taking limits. Unless your language is overloading division to be more than a mathematical op, divide by 0 should be an error.
–
nezroyJan 8 '09 at 21:14

Checking before the division occurs is not the best solution. That would slow down the computation considerably to handle the rare case when the divisor is zero.
–
kevin clineNov 16 '11 at 4:20

Even if taking limits; lim x->0 1/x is undefined as it could be positive or negative infinity.
–
Anton GolovJan 31 '12 at 1:34

@AntonGolov: The ideal handling of zeroes, infinities, etc. would be to have one unsigned zero, along with positive and negative infinitesimals (the latter two being produced by multiplications or divisions whose result would be too small to represent). Adding two infinitesimals of opposite sign should yield unsigned zero; in all other cases, adding something to an infinitesimal should simply yield the other operand. Under such rules, division by "unsigned zero" should yield NaN, but division by an infinitesimal would yield positive or negative infinity, yielding correct limit behavior.
–
supercatJul 12 '12 at 17:59

The existing design choice is correct. If you want NaNs and infinities you should be computing in the floating-point space to begin with. Today's floating-point units do integer arithmetic very efficiently.

A language that handles divide by zero nicely is Standard ML: dividing by zero is guaranteed to raise an exception, but it's an exception (Div) like any other and can be caught by user code.

Um, what is so special about Standard ML's exception? Java has ArithmeticException, and C# must have something equivalent. (Not saying you claimed ML was unique, just wondering why you mentioned this particular language!)
–
Andres F.Jan 31 '12 at 0:29

I think division by zero is pretty much the standard example of how exceptions work. Higher level languages throw DivisionByZero exception, the x86 hardware (in protected mode) throws a division by zero exception as wel, etc. Exceptions can be handled.

A division by zero is an error. Failing to report a severe error like that could have disastrous consequences.

What would you prefer: if the software of the X-Ray machine that is scanning you would throw an exception and shut down if it divided with zero for some reason, or just returned positive infinity and this would be the X-Ray dose you would get?

What do you prefer, a life support machine that halts that divides by zero, or just prints NaN since it was for display purposes? We both can make up examples that assume poor testing or design.
–
PyrolisticalJan 5 '09 at 19:05

2

Pyrolistical: Obviously, on life-critical systems, robustness is extremely important. That's why a life support machine should throw an exception and reset if it divides by zero. Otherwise, it might kill the patient by using invalid data. It should never ignore division by zero.
–
Tamas CzinegeJan 5 '09 at 19:19

You missed by point. I am saying for life critical software, no matter how divide by zero is handled, it would be a great failure on testing and design if those two examples were to occur.
–
PyrolisticalJan 5 '09 at 19:28

True, it shall never happen. But what if it still happens? No amount of good development practices, code reviews etc could filter out all of the bugs in all possible circumstances. There must be an error handling mechanism, and dividing by zero is definitely an error. Not handling it could be fatal.
–
Tamas CzinegeJan 5 '09 at 19:37

@Pyrolistical I would expect the life support machine to halt on divide by zero and report the error (unless this error is explicitly handled by the programmer, which means he/she thought about it). Otherwise the life support machine is in an inconsistent state, and who knows what it will do to the patient? It's likely the code relies on the result being something other than NaN, in which case continuing would be disastrous.
–
Andres F.Oct 9 '13 at 17:42

An integer, by definition, is a whole number.

NaN, infinity, etc are NOT integers.

If you expect to be working with objects that are not integers, you should use objects that support the needed representations.

If you are expecting your data to always be representable by an integer, then by all means use an integer type, and if there is an error you'll need to handle it, but the bad data is the culprit - not the program (as long as the program is designed correctly). The program should then decide how to recover depending on the design.

So, in short, the current programming languages offer everything you need - an integer type for integers, and various other types for mathematical representations that are not whole numbers.

Please don't turn the integer into something it's not - there's no reason to make the integer handle non-integer values.

Division by zero doesn't make sense algebraically: a / b is defined as the number c such that c * b = a, but if b = 0, the only possible value for c * b you can produce is going to be 0, while a can be any number. So you can't pick a c even if you invent one - you're going to have to special-case that c in your code anyway.

Your program probably makes some implicit assumption somewhere that / means what it is defined to mean algebraically, and that assumption goes out the window as soon as you assign a number to be the value of division by zero. So it's best to blow up right away, where the problem arises.

I don't think there's a nice way to handle it. Throwing an exception is probably the best thing to do, because it forces the developer to think about it, an code correctly. Assuming 1/0 returned NaN, what happens when you try to add NaN to something else, does it throw an exception, or does it return NaN again (same could be said for infinity). Since there is really no define action to take, the developer should program what they want to happen when divide by zero occurs.

The way IEEE 754 defines it is operations using NaN produces NaN, and NaN does to equal NaN.
–
PyrolisticalJan 5 '09 at 19:06

@Pyrolistical That's not helpful. Say the result of the division represents the number of CCs of the drug an hipothetical life support machine must inject to its patient. If this "number" is NaN, what must the machine do? Inject zero CCs? Inject MAX_INTEGER CCs? Who knows? The behavior is undefined. The only reasonable course of action is to fail and report the division by zero.
–
Andres F.Oct 9 '13 at 17:45

@AndresF.: If the number of CCs of drug required is NaN, the machine can sound an alarm at that time. When performing floating-point maths, it's difficult to know in advance which operations will succeed without problems, and unless the action one would take when an individual operation fails is different from what one would do after a sequence of actions yields NaN, performing all the calculations and checking the result for validity is faster and no less useful than checking each step.
–
supercatJan 17 '14 at 0:42

@supercat My point in my previous comment was, btw, that whatever you choose to do (throw an exception, make the result NaN), it must put the program in an error state that you cannot ignore. A division by zero must force you to deal with it. Throwing an exception is an acceptable way of doing this; not saying it's the only way. If, like you say, one NaN in the chain causes the end result to be NaN, and then you cannot ignore it's NaN, that's also valid. The key point is that at the end you must not be able to ignore the division by zero error.
–
Andres F.Jan 17 '14 at 12:43

If something fundamental like divide by zero doesn't matter, then you don't need the operation at all in the first place.

If you can't count on the results then how can you ever use the results, in other words! This kind of halt alerts you to a no-win, faulty logic situation that needs fixing and if you try to ignore it then every operation after that point is invalid.

Well, I don't know if it's too important, but I think it throwing an error is reasonable. I'm guessing this is highly subjective, but to me having NaN defined in a language is a workaround for something that shouldn't be done. Dividing by zero is meaningless, and thus an error should be thrown.

It is definitely a must for a good programming language to support detection of integer overflows because they are a common error and the overflow detection relies on CPU flags that are available only to the compiler, but not the programmer (except in assembler ;-) ).

Basically there are the following strategies to handle something like that:

Don't handle it. That's what C/C++ does.This results in the corresponding data types effectively being defined as modulo their size.

Result is largest possible value for the specific data type.

Exception.

Run-time error.

Error indicator (e.g. errno in C).

Special return value (NaN), like usually for floating point.

For every of these strategies, there are situations where they are appropriate and where they are not.

If we look at the strategies,

No. 1 is very error-prone and for the cases where it is really needed, it is redundant if the programming language has got a modulo operator. A good compiler should be able to detect this situation and simply disable overflow checking for this calculation, so that doesn't cost any performance, compared to the C/C++ way.

No. 2 has got the disadvantage of not being able to tell if the calculation delivered the largest result possible or an overflow occured. However, there are applications where an inaccurate result is better than a program error, so this can be useful. For these few cases, it can be emulated with any of the methods 3.-6., so it's redundant.

The strategies 3 & 4 are quite similar, so we could come along with one of them, preferably exception because it's more universal.

No. 5 belongs into the same category, but there are cases where it can simplify error handling over exceptions, etc. It's redundant with the other possibilities 3, 4 and 6
In languages that have an inline assembler, it's possible to examine the corresponding CPU flags in a non-portable way to achieve this, as long as the CPU supports this detection at all (has anyone know one that doesn't?).

No. 6 has also got huge disadvantages, it leads to the definition of the integer type being different from what's common and the special value must not be used accidentially, e.g. as the result of a successful calculation, so the compiler has to generate additional checking code for calculations. Therefore I don't like it.

In my view, the default behaviour should be an exception or something similiar to ensure that the error is noticed. The programmer should be able to disable this or switch to a "less destructive" strategy like 5 by using compiler switches or pragmas.

Matlab, a numerical computing environment and programming language, has Inf:

Inf returns the IEEE arithmetic representation for positive infinity. Infinity results from operations like division by zero and overflow, which lead to results too large to represent as conventional floating-point values.

Inf('double') is the same as Inf with no inputs.

Inf('single') is the single precision representation of Inf.

Inf(n) is an n-by-n matrix of Infs.

Inf(m,n) or inf([m,n]) is an m-by-n matrix of Infs.

Inf(m,n,p,...) or Inf([m,n,p,...]) is an m-by-n-by-p-by-... array of Infs.

Matlab doesn't have integers, it just doubles pretending to be integers.
–
PyrolisticalJan 5 '09 at 19:07

actually the limit of a/x for +x -> 0 is positive infinity for positive a, so you can say the limit of 1/0 is infinity
–
PyrolisticalJan 5 '09 at 19:26

@Pyrolistical - Yet your claim is only true if x != 0, even if it is infinitesimally close to zero. An answer to this question has been attempted for thousands of years, including by Newton and Pythagoreas. The problem with allowing it to be a number (even if the number is infinity) is that using that as a fact would allow many laws of nature (particularly in physics) to be violated by using some fancy math which relies on division by zero to return a valid result.
–
DunkJan 30 '12 at 23:28

You can think of it this way. No matter how small x becomes, there is always some infinite number of those small x's that divide into the top number. However, if x == 0, then there is no amount of infinite x's that could ever divide into any number.
–
DunkJan 30 '12 at 23:33

@Pyrolistical: the limit of 1/x when x -> 0 and 1/0 are completely different things. 1/0 is undefined no matter how you look at it.
–
Andres F.Jan 31 '12 at 0:34