61

We all know 0/0 is Undefined and returns an error if I were to put it into a calculator, and if I were to create a program (in C at least) the OS would terminate it when I try to divide by zero.

But what I've been wondering is if the computer even attempts to divide by zero, or does it just have "built in protection", so that when it "sees" 0/0 it returns an error even before attempting to compute it?

gnat
  • 21,442
  • 29
  • 112
  • 288
Ankush
  • 821
  • 1
  • 8
  • 12
  • 11
    0/0 is undefined, any other number / 0 is a different kind of error, you seem confusing the two – edc65 Feb 26 '16 at 14:44
  • 2
    From a mathematical point of view, x/0 *is* undefined for all (at least real) values of x – Xophmeister Feb 26 '16 at 14:56
  • 8
    Any number divided by 0 is undefined, mathematically speaking. – ManoDestra Feb 26 '16 at 15:44
  • 0/0 is undefined, but if it did have a value it would be 1. Any other number divided by 0 is undefined, but if we included infinity in the possible answers it would be infinity. – jwg Feb 26 '16 at 16:26
  • 12
    @jwg: "if it did have a value it would be 1" - not necessarily; there are [whole branches of mathematics](https://en.wikipedia.org/wiki/Differential_calculus) devoted to what the value might be in different circumstances :) – psmears Feb 26 '16 at 17:01
  • 11
    To clarify the terminology here, 0/0 is called an **indeterminate form** while x/0 for nonzero *x* is **undefined**. A calculation that ends up with 0/0 can often be calculated in a different way to give a real answer, whereas x/0 is essentially meaningless. – Era Feb 26 '16 at 17:48
  • 9
    @jwg you might be interested in l'hopital's rule then. There are definitely cases where 0/0 does not imply a value of 1. – d0nut Feb 26 '16 at 18:48
  • 1
    @jwg 0/0=0 would make more sense to me. For example, 0/0 successful attempts => 0% success rate and 0% failure rate. And 0/x would no longer need an exception for x=0. – Muhd Feb 26 '16 at 21:54
  • 4
    This reminds me of a Feynman story where he talks about electro-mechanical calculators. If you accidentally divided something by zero, the rotor that performed the computation would just spin and spin and spin, which is why these machines had big red "CANCEL" buttons on them. – Gretchen Feb 26 '16 at 22:51
  • 1
    @Era I believe you are implicitly speaking about limits. `0/0` is undefined. A limit of a fraction where both numerator and denominator tend to `0` may still converge to some value (not necessarily `1`, or even finite) that is computable in some way. But the number `0` divided by the number `0` is undefined. In the same way the value of the limit for `x` that goes to infinity of `0*x = 0`, which is different than `f(x)*x` where `f(x)` tends to `0` with `x` going to infinity: that would be an indeterminate form. – Bakuriu Feb 27 '16 at 13:00
  • @Muhd - anything divided by itself is 1. However, anything divided by zero is undefined. Therefore, 1 = 0/0 = undefined, thus 1 is undefined, and mathematics has just fallen apart at the seams. [Prepare for the end of the world....](https://www.youtube.com/watch?v=-hJQ18S6aag) (And, BTW - no, it was NOT GMT, it was Eastern Standard - if the word of God is anything to go by... :-) – Bob Jarvis - Слава Україні Feb 27 '16 at 18:02
  • Given any non-zero `x`, `x/0` is undefined. 0/0 is not undefined. It's worse than undefined. It's indeterminate. – David Hammen Feb 27 '16 at 22:12
  • "Too broad?" Really? We have an IEEE spec and two very popular architectures (AMD64 and ARM) with very well-defined behavior. Y'all need to chill out. –  Feb 28 '16 at 01:27

5 Answers5

76

The CPU has built in detection. Most instruction set architectures specify that the CPU will trap to an exception handler for integer divide by zero (I don't think it cares if the dividend is zero).

It is possible that the check for a zero divisor happens in parallel in hardware along with the attempt to do the division, however, the detection of the offending condition effectively cancels the division and traps instead, so we can't really tell if some part of it attempted the division or not.

(Hardware often works like that, doing multiple things in parallel and then choosing the appropriate result afterwards because then each of the operations can all get started right away instead of serializing on the choice of appropriate operation.)

The same trap to exception mechanism will also be used when overflow detection is turned on, which you ask for usually by using different add/sub/mul instructions (or a flag on those instructions).

Floating point division also has built in detection for divide by zero, but returns a different value (IEEE 754 specifies NaN) instead of trapping to an exception handler.


Hypothetically speaking, if the CPU omitted any detection for attempt to divide by zero, the problems could include:

  • hanging the CPU (e.g. in an inf. loop) — this might happen if the CPU uses an algorithm to divide that stops when the numerator is less than the divisor (in absolute value).  A hang like this would pretty much count as crashing the CPU.
  • a (possibly predictable) garbage answer, if the CPU uses a counter to terminate division at the maximum possible number of divide steps (e.g. 31 or 32 on a 32-bit machine).
Erik Eidt
  • 33,282
  • 5
  • 57
  • 91
  • Thank you for the very thorougher answer :) I was just wondering if you could shed some light on what would happen if the CPU didn't catch a device-by-zero - basically what problems would you run into? Would the CPU just ignore it, or will something more drastic like a system crash occur? thanks :) – Ankush Feb 26 '16 at 07:54
  • 51
    @Ankush A "system crash" isn't really something that happens at the CPU level. The most likely behavior of a CPU that did not trap on divide by zero would be that it simply does the division operation, produces some nonsense result and keeps going. Just like when you add two integers that happen to overflow. – Ixrec Feb 26 '16 at 08:00
  • 6
    For floating point, the choice between "NaN" and "trap" is usually settable by flipping flags in the FPU. – Vatine Feb 26 '16 at 11:45
  • 10
    @Ankush In case what lxrec said was unclear: as far as the CPU is concerned, there is no such thing as a crash. – user253751 Feb 26 '16 at 12:32
  • 7
    @Ankush Few situations cause a CPU-level "system crash". In those cases we are talking about things like thermal protection shutdown (overheat protection), [triple faults](https://en.wikipedia.org/wiki/Triple_fault) and similar situations. Almost every crash you will encounter in ordinary use, including [invalid opcodes](https://en.wikipedia.org/wiki/Illegal_opcode), are handled by trapping and recovering in some manner, or simply ignoring the error and continuing execution in a potentially unclean state maybe having set some error flag. – user Feb 26 '16 at 12:41
  • 3
    @Ixrec: Well I guess a badly-designed (or buggy) CPU could freeze with an infinite microcode loop when dividing by 0, requiring a power cycle. – Bergi Feb 26 '16 at 12:47
  • 8
    If you did not trap divide by zero, the result would be, in programming parlance, "Undefined Behavior." This means the computer may do anything. It may, as Bergi mentions, enter a buggy loop and hang. It may simply output some unspecified series of bits that happened to be what came of their implementation of division logic (remember, a computer does not "divide" in the mathematical sense. It does an operation on two numbers, which is close enough to division that we typically get to simply call it "division".. see also floating point roundoff). – Cort Ammon Feb 26 '16 at 14:43
  • 1
    For floating point numbers, actually, only 0/0 (or NaN/0) gives NaN, x/0 for other x gives positive or negative infinity. – Paŭlo Ebermann Feb 26 '16 at 19:31
  • @Bergi yeah, although the version that's prone to looping forever is probably too inefficient to use much in practice. The constant-time ones that *are* commonly used look like they would give a quotient of -1 (or maxint) and a remainder that looks like the original dividend. – hobbs Feb 26 '16 at 19:52
  • 2
    @CortAmmon: Whether an untrapped division by zero would cause "undefined behavior" would depend upon the specification of the language in question. A language could perfectly easily specify that for any integer x, x/0 will yield x; the performance cost would usually be relatively slight, and it may allow some algorithms to be written more conveniently than would otherwise be possible. – supercat Feb 27 '16 at 00:04
  • @supercat Yes, a language could specify it. A language could do anything you want. However, can you name a single language which implements that behavior? Given the OP's question, I felt exploring the theoretical possibility of languages which permit dividing by zero would raise confusion, especially with phrases like "built in protection" and "sees `0/0`" I'll save the theoretical stuff for your questions ;-) – Cort Ammon Feb 27 '16 at 00:43
  • 1
    @CortAmmon There exists a C dialect whose integer division operator defines `x / 0` as the largest integer of the same sign (that is, `INT_MIN` or `INT_MAX`) to make perspective projection work approximately as expected. I've developed a game in this dialect. – Damian Yerrick Feb 27 '16 at 04:44
  • Many languages which are designed for processors that don't trap on divide-by-zero simply have division by zero yield some value. While there are some hardware designs where trapping divide-by-zero might be easier than having it simply produce a value (e.g. there's no divide-by-zero-trap hardware, but a circuit issues a fault trap if one instruction takes too long to execute) I don't see much purpose to such traps otherwise. – supercat Feb 27 '16 at 17:05
  • Re *shed some lIght on what would happen if the CPU didn't catch a device-by-zero*: ok. The division work is basically what you learned as "long division", though easier in binary. Write code to do that, using bit operations and loops (like we did with old CPUs that didn't have it built in!). I expect a real hardware implementation to have a fixed number of iterations, so it won't hang. It will generate *some* answer. Try it on paper to see what you get. Exact details depend on the exact logic and branch order. – JDługosz Feb 28 '16 at 07:45
34

It depends on the language, on the compiler, on whether you are using integers or floating point numbers, and so on.

For floating point number, most implementations use the IEEE 754 standard, where division by 0 is well defined. 0 / 0 gives a well defined result of NaN (not-a-number), and x / 0 for x ≠ 0 gives either +Infinity or -Infinity, depending on the sign of x.

In languages like C, C++ etc. division by zero invokes undefined behaviour. So according to the language definition, anything can happen. Especially things that you don't want to happen. Like everything working perfectly fine when you write the code and destroying data when your customer uses it. So from the language point of view, don't do this. Some languages guarantee that your application will crash; it's up to them how this is implemented. For those languages, division by zero will crash.

Many processors have some kind of built-in "divide" instruction, which will behave differently depending on the processor. On Intel 32bit and 64 bit processors, the "divide" instructions will crash your application when you try to divide by zero. Other processors may behave differently.

If a compiler detects that a division by zero will happen when you execute some code, and the compiler is nice to its users, it will likely give you a warning, and generate a built-in "divide" instruction so that the behaviour is the same.

gnasher729
  • 42,090
  • 4
  • 59
  • 119
  • 22
    *"On Intel 32bit and 64 bit processors, the "divide" instructions will crash your application when you try to divide by zero."* Citation needed. CPUs don't have any idea about applications, they execute instructions and (if we include the MMU) enforce memory access limits (unless in [ring 0](https://en.wikipedia.org/wiki/Protection_ring), or equivalent in non-Intel-x86 architectures). That the instruction is part of Application A rather than Application B or Operating System Component C is irrelevant to the CPU; whether the instruction can be Instruction X or use Memory Address Y is relevant. – user Feb 26 '16 at 12:44
  • 1
    To add to @MichaelKjörling comment: The OS has ways of notfiying the application of this (and other kinds of errors). In the windows world it is the `EXCEPTION_INT_DIVIDE_BY_ZERO` value in the `EXCEPTION_RECORD` which will be handled by the (hopefully) installed [Structed Exception Handling](https://msdn.microsoft.com/en-us/library/windows/desktop/ms680657%28v=vs.85%29.aspx) Handler – user45891 Feb 26 '16 at 15:23
  • 1
    Sometimes they do things other than guaranteeing that your app will crash. For example, many languages/platforms guarantee that they will throw an exception on division by zero. You can then catch and handle said exception without crashing. – reirab Feb 26 '16 at 19:12
  • 2
    You can delete the "may" within "Other processors may behave differently": On the PowerPC Platform, the division just produces a zero result on division by zero. Which is much more useful than the panicking behavior of the X86 platform. – cmaster - reinstate monica Feb 27 '16 at 14:00
13

Seems like you're wondering what would happen if someone made a CPU that doesn't explicitly check for zero before dividing. What would happen depends entirely on the implementation of the division. Without going into details, one kind of implementation would produce a result that has all bits set, e.g. 65535 on a 16-bit CPU. Another might hang up.

NVZ
  • 103
  • 1
  • 4
Bingo
  • 163
  • 2
2

But what I've been wondering is if the computer even attempts to divide by zero, or does it just have "built in protection", so that when it "sees" 0/0 it returns an error even before attempting to compute it?

Since x/0 makes no sense, period, computers must always check for division by zero. There's a problem here: Programmers want to compute (a+b)/c without having to bother to check if that calculation even makes sense. The underneath-the-hood response to division by zero by the CPU + number type + operating system + language is to either do something rather drastic (e.g., crash the program) or do something overly benign (e.g., create a value that makes no sense such as the IEEE floating point NaN, a number that is "Not a Number").

In an ordinary setting, a programmer is expected to know whether (a+b)/c makes sense. In this context, there's no reason to check for division by zero. If division by zero does happen, and if the machine language + implementation language + data type + operating system response to this is to make the program crash, that's okay. If the response is to create a value that might eventually pollute every number in the program, that's okay, too.

Neither "something drastic" or "overly benign" is is the right thing to do in the world of high reliability computing. Those default responses might kill a patient, crash an airliner, or make a bomb explode in the wrong place. In a high reliability environment, a programmer who writes (a+b)/c will be picked to death during code review, or in modern times, perhaps picked to death automatically by a tool that checks for verboten constructs. In this environment, that programmer should instead have written something along the lines of div(add(a,b),c) (and possibly some checking for error status). Underneath the hood, the div (and also the add) functions/macros protects against division by zero (or overflow in the case of add). What that protection entails is very implementation specific.

David Hammen
  • 8,194
  • 28
  • 37
  • Just because NaN doesn't obey the arithmetic you learned in school doesn't mean it makes **no** sense. It obeys *different* arithmetic – Caleth Aug 01 '18 at 16:03
-2

We know by now that x/0 and 0/0 do not have well defined answers. What happens if you attempt to calculate 0/0 anyway?

On a modern system, the calculation is passed to the MPU within the CPU and is flagged as an illegal operation, returning NaN.

On a much older system, such as '80s home computers that had no on-chip division, the calculation was done by whatever software was running. There are a few possible choices:

  • Subtract smaller and smaller copies of the divisor until the value reaches zero and keep track of which sized copies were subtracted
    • If it checks for zero before the first subtraction, it will exit quickly and the result will be 0
    • If it assumes it must be able to subtract at least once, the result will be 1
  • Calculate the logarithms of both numbers, subtract them and raise e to the power of the result. A very inefficient method compared to the above subtraction method, but mathematically valid
    • An overflow might occur trying to calculate log(0) and the software would either use its error handling routines, or crash
    • The software might assume that all logarithms can be calculated in a fixed number of steps and return a large, but incorrect value. Since both logarithms would be the same, the difference would be 0 and e0 = 1, giving a result of 1

In other words, it would be implementation dependant what would happen and it would be possible to write software that produces correct and predictable results for every value but seemingly strange values for 0/0 that are nonetheless, still internally consistent.

CJ Dennis
  • 659
  • 5
  • 15
  • 3
    This question is about dividing by zero in the integers, and there is no such thing as `NaN` in the integers. – David Hammen Feb 27 '16 at 21:56
  • 3
    No CPU is going to calculate logs and subtract to calculate the result of division. Logarithm instruction timing is several orders of magnitude greater than a division. What is the value of log(0)? – wallyk Feb 27 '16 at 22:00
  • 1
    @DavidHammen The OP never once mentioned integers, and nor did anyone who commented on the question. Integers are only mentioned in answers. – CJ Dennis Feb 29 '16 at 03:24
  • @wallyk I already said in my answer that that logarithms are `very inefficient` for division. The cost for arithmetic is (addition = subtraction) <= multiplication <= division. If you don't have an MPU that can do division in the same number of clock cycles as addition (usually one), then division is more expensive than addition and subtraction and usually more expensive than multiplication too. – CJ Dennis Feb 29 '16 at 03:30