When Smart Ships Divide by Zer0 – Stranding the USS Yorktown (2018)
medium.com
medium.com
Counterarguments in comments perhaps. Someone have a driving passion for this particular edge case of missed input validation being wildly more important than all the others?
How about modulo zero? That can be completely correctly define or a floating point exception if you decided to define it in terms of divide and also decided divide should do that.
What about floating point? It gave up on reflexive equality and yet programs do things with doubles despite that.
The integer divide zero industry best practice of promptly falling over isn't an axiom of reality. It's another design mistake from decades ago.
It's not. Division (edit: of a positive integer) by zero is better approximated by +infinity rather than zero.
In real life to divide something into zero groups is nonsensical, thus the number system in programs should reflect this. In the exceptionally-rare case where you want to divide by zero and it makes sense (can't think of a scenario where that's true but let's stipulate), then you can use your language's equivalent of try/catch or (if (zerop x) ...) to get around it.
Don't fuck up normal mathematics for the rest of us just because some lazy programmer doesn't like to add error checking.
No it's not. Division by zero is UNDEFINED. How does a calculation return +infinity anyway?
On the positive side of the graph, 1/x approaches +infinity. However from the negative side of the graph 1/x approaches -infinity. So at zero, 1/x is simultaneously +infinity and -infinity, which is not possible. The answer to 1/0 is "there is no answer" which is UNDEFINED.
A reasonable result for a calculation is to return "?" or possibly NULL or nothing, depending on what other parts of the system are expecting.
Yeah OP is suggesting that the answer to lim x-> 0 1/x = infinity and thus that’s an intuitive answer. Unfortunately that’s obviously not correct precisely because it depends which side from 0 you approach and why just 1/0 is undefined (you could argue about 0+ and 0- but I view that more as IEEE754 weirdness that is used in niches rather than something that would meaningfully change the situation)
> How does a calculation return +infinity anyway?
Not sure what your actually asking but floating point representations generally support a concept of +/- inf.
> A reasonable result for a calculation is to return "?" or possibly NULL or nothing, depending on what other parts of the system are expecting.
That’s what floating point NaN is
I used the word "approximated" for a reason.
I'll cop to the fact that I was only considering positive integers but your response is needlessly pedantic given the context of what I wrote.
Computer integers aren't the real numbers you learned about in gradeschool. INT_MAX+1 is not greater than INT_MAX. :)
x/0 = program explodes is also a justifiable choice. It is not however more or less fundamentally correct than making the result 0.
Floating point division by zero doesn't (typically) crash programs the way integer division by zero does (it typically returns a NaN-- and the programmer is free to turn nans to zeros if they like :)).
Nope. You forgot that there's a requirement that r < q. Otherwise I could say e.g. 5/2 = 1, which is certainly no less valid than saying that 5/0 = 0, but not something that anyone sane wants.
No, x is an utterly non-sensible value of r.
> remove the mod 0 subset you have the unmodified set of integers itself-- the remainder can only sensibly be an identity in that case.
What are you talking about? There are no possible remainders mod 0 (just as there is one possible remainder mod 1 and there are 2 possible remainders mod 2) and there is no sensible definition of the remainder function; defining it to be identity is no less silly than defining it to be, IDK, 7.
Why would anyone think computer integers are real numbers? Anyone who's given it a modicum of thought will know intuitively they're a subset of "real life" integers, not reals.
>using 0,x is a perfectly reasonable and intuitive way of defining things.
I would argue it's neither reasonable nor intuitive. If you want to create some special data type then have at it, but if the behavior of `int` doesn't approximate the behavior of IRL integers, call your data type something else.
Seems to me that ship has sailed!
I mean that seriously, is this just a random 78.6/0.0 or is it part of a string of computations based on spatially related measurements (ie. physics | geophysics processing).
The answer you're looking for is the behaviour to trigger when an undefined result occurs.
That behaviour can and does vary with respect to the bigger picture.
Instrumentation can return a NULL (no reading - not a number and not a zero), a zero (meaning zero was measured), a zero (meaning non zero was measured but smaller than the granulated bucketing of analog -> digital). Piped data can suffer a static burst, data in is good, data out is bad, may include zeroes.
Desired behaviour may well be to use every value that you can be 'sure' of and running filter replace values that are "bad" | suddenly spike | goto zero - a smoothed "bestguess" result is produced for use (or a local limit that a series was trending toward) and anomalies are flagged for highlighting | operator attention in some manner.
You really can't though.
> If x/0 is a value, then the theorem should extend to c=0, too.” This is wrong. The problem is not that 1/0 was undefined. The problem was that our proof uses the multiplicative inverse, and there is no multiplicative inverse of 0. Under our modified definition of division, we still don’t have 0⁻, which means our proof still does not work for dividing by zero. We still need the condition. So it is not a theorem that a * (b / 0) = b * (a / 0).
This is like saying there's nothing wrong with defining 2 + 2 = 5, and addition will still be associative because (a + b) + c still = a + (b + c) unless b = 2. Like, sure, you can redefine division to not have the normal properties that it does, and then argue that your redefinition is sound because the theorems only apply to things that have the normal properties of added numbers. But that's not what + means!
If these people really believed the arguments they're making, they would actually define x/0 = 5, or 19, or something on those lines.
I'm saying that's a false distinction, because as soon as you have that deviation from expected meaning, you have valid theorems that silently stop being valid and your formal system quickly breaks down. And while you can redefine your way out of each individual instance of this, everything you redefine just means more and more theorems that don't have their normal meaning which in turn means more things that you have to redefine.
> You could just say something like "to simplify error handling, our programming language uses a 'zivision' operator that behaves exactly like regular division except zivision by zero is defined as zero".
This would be a much better approach, because then existing theorems that use or refer to division are obviously not necessarily true of zivision and if you want to use those theorems to talk about zivision then you have to check (and prove) that they're actually valid first.
Division by zero returning a zero is a pretty bad and confusing result mathematically.
How about 5 - 8 = 0? Sensible result for the natural numbers.
X + 7? Surely you meant addition modulo 2^64.
What's the count leading zeros on zero? Is it zero, 64, random noise found in a register?
What's X shifted by word size? Zero? Minus one? X?
These are all choices. Some are familiar. But knowing integer divide zero is wrong is a tenant of faith.
It isn't nonsense. 7/2 represents a real number. You can round a real number up or down. So you can round 3.5 to 3. 7/0 doesn't represent a real number. It doesn't even make sense to do anything to an undefined number.
All rational numbers are real numbers.
> Why not a complex number?
What?
> That you especially like the real numbers is particularly unfortunate
It's not a matter of me liking or disliking real numbers. It's just that the topic at hand is about real numbers.
> when they are so poorly represented in essentially all programming languages.
Not essentially all programming languages. In every single one. It's the nature of real numbers. It's also not just 'programming languages', it's hardware as well.
Indeed, which is why decent languages don't do that. Different symbol like // for truncating division if that's what you want.
> How about 5 - 8 = 0? Sensible result for the natural numbers.
Nah. Similarly, don't call that operation -; - underflowing should be an error.
> X + 7? Surely you meant addition modulo 2^64.
Surely you didn't. If your language does that, get a better language.
> What's the count leading zeros on zero?
What's the "count leading zeros" on anything? Numbers don't have leading zeroes (or rather, a number with leading zeroes is equivalent to one without them).
> What's X shifted by word size? Zero? Minus one? X?
No, it's X shifted by word size. (Which is a value bigger than a word, sure).
If you want weird bit-twiddly operations because they're what your hardware implements efficiently, by all means have them. But don't use the standard mathematical symbols for operations that don't have the standard mathematical behaviour. And that includes a "divide" operation that silently accepts 0 and returns some normal value.
Making sure you don't divide by zero is just one of those things programmers learn... like making sure you don't derefence null or go beyond the size of your array, or overflowing... not clear to me that masking that helps, maybe the ship wouldn't strand but instead it'd run into a bridge.
Disagree. The whole point of calling it '/' is to tell the reader that it is mathematical division.
> Making sure you don't divide by zero is just one of those things programmers learn... like making sure you don't derefence null or go beyond the size of your array, or overflowing... not clear to me that masking that helps, maybe the ship wouldn't strand but instead it'd run into a bridge.
In all of those cases it's much better for your program to explode quickly and loudly than silently continue (e.g. you'd hope dereferencing null triggered an error rather than just letting your program continue). Defining x/0 = 0 is masking the error and continuing, which tends to lead to corrupt data and silent wrong results.
Well, we call a different operation "+", and there's a decent chance that either wraps a uint_max, or triggers arbitrary undefined behaviour when it goes past a limit, or that it maps to a floating point operation where x + 1 == x for large x. That's not especially like "mathematical addition", whatever you have in mind for that definition.
I'm saying we shouldn't, and good languages won't. Using + for modulo addition is maybe acceptable, that's a reasonably standard usage in mathematics and has most of the behaviour you'd expect from addition, but using + to denote something that has undefined behaviour or suddenly shifts to floating point is certainly wrong.
> A hardware example of exception handling is the IEEE 754 standard for floating point arithmetic which defines values for various exceptions (e.g. infinity for divide-by-zero)
It's wrong.
How is infinity returned as a result anyway? It's not a number, and it's not <the largest number the computer can return> either.
https://www.gnu.org/software/libc/manual/html_node/Infinity-...
I think what I would like is perhaps a way to have something almost like an interrupt. And being able to set what the interrupt does or swap between different interrupts. At runtime we can see the denominator is zero, so trigger the interrupt. For a set of functions, I can set an interrupt where a divide by zero does return zero, these would be functions whose callers can safely handle the zero or perform some default state at zero. But other functions, maybe there is a different default value that callers can use and it not screw everything up.
Some may gripe about, but its a mathematically in correct answer. Sure, it is. But for systems, especially saftey critical systems, I'd rather know that in the event I didn't properly guard against a 0 in the denominator, a behavior that I can account for is guaranteed to happen (some safe default).
I agree with this. Forcing every instance to be 0 might hide the issue as 0 could be a valid if unexpected result in situations which might make debugging more difficult. The same reason === is a thing. NaN seems plausible yet equally awkward. Null could work too