Oh jeeze... to me that almost nullifies all of the points in the article. It does an alright job explaining how 1/0 = 0 is at least consistent with other notions in the language, but to hear that the same logic can’t be applied to floats is just... well, objectively it’s a mess.
The floating point standard says that division by 0.0 should be Infinity and provides a value for it. The integer math, all possible values are used for numbers, so division by zero is undefined behavior.
And from there, every language is potentially going to have a mess of inconsistency to deal with.
You can make 1/0 = Infinity so long as you box all your integers. That is, its not using the machine type, but I type that is a wrapper that can be the machine type or Infinity. And every user takes a large performance hit even if they will never divide by zero.
For some languages boxing integers is not a bad thing because they already do it. Why do they do it? Usually, because of another not math problem. Overflow and underflow:
What is 0 - 1? Well, its -1 right? Except of course if you have an unsigned integer, then its the max value of the integer. And what if you had 1 to the max value that the computer can represent? You wrap around. Some languages make all integers protect you from this and take a performance hit to be able to box and be able to represent numbers better as we expect them to work. In return, you can not do integer math as fast as you could.
Computers and numbers... its an inconsistent mess and a series of tradeoffs for any language of performance and various possible errors.
I'm going to talk about this and more in my post.
What does your favorite programming language return for 3/2 as compared to 3.0/2.0? Many will return different values.
EDIT:
for clarity of my point: integer math that uses machine types is pretty surprising compared to what we would expect from "math" in general for division.
just so long as you don't expect a consistent answer between python2.7 and 3.x... >.>
Floating point doesn't even form a Ring, because the operation is not associative[0]. Coq, for instance, defines the operation for QArith, which are the rational numbers. The representation is a pair (Z, positive), where Z is an integer and positive is a positive number (i.e., 1,2,...). QArith does form a field in the usual sense.
Integers are not a Field (unless you pick Z/p for some prime p), and machine words, signed or unsigned are even less of a mathematical object with the usual operations. So you can do almost anything you want to them from a programming perspective, including 1/0 = 0.
As Hillel writes, what to do will make sense in some settings, but not in others. You may want MAX_INT in some situations, and 0 in others. And this requires a check, partiality or not. Rejection of the case x/0 has more to do with the notion that it is usually a corner case where you want the programmer to think about what the result should be.
[0] The reason is that any addition can incur information loss, and the further away from 0 you are, the more information is lost. Thus, the order in which you add values matter.
Division with floats doesn't usually have a definition like that, so you don't end up in a similar situation. Plus, floating point math can have denominators get really close to 0 and have the result of the division tend toward the infinity value. Ints don't have values close to 0 or an infinity to represent what that division would tend toward.
And I was thinking that perhaps 0x80000000 (in two's complement arithmetic) would be a good value for integer NaN. This value is already fixed point with respect to negation, so why not make it into an exception on its own right?
But it would mean to rethink all the hardware which I don't think is an option.
In any case, I think to set 1/0 to 0 is a bad idea, but I could imagine setting x/0 to 0x80000000 (interpreted as NaN) to make more sense.
Ah, that seems rather reasonable. For whatever reason, the OP had me thinking that Pony was replacing the ordinary semantics of IEEE 754 floating point division (probably because he talked about fields and multiplicative inverses).
Having 1/0 = 0 seems like a very reasonable choice, especially if you have 1%0 = 1 as well. Of course, if anyone thinks they will actually encounter division by 0 in their code, and needs to treat it as an error, they can always test for it.
So you may be saving some developers time in operator overloading, etc. More important than the actual binary decision itself is having well-documented behavior. Have not tried Pony yet, but will take a look. Good discussion, keep it up!
https://tio.run/##K8jPq/z/PzG5JL9IwTcxM49LAQjyUssVkotSE0tSNV...
`I64.max_value() + 1` gives the expected result.
I'm going to have to look into that.
Thanks.
Unfortunately LLVM considers division overflow undefined: http://llvm.org/docs/LangRef.html#id109
If it's any use, you can see what Julia ended up doing here: https://github.com/JuliaLang/julia/issues/8188
And thank you for the additional info, I've updated the issue I opened accordingly:
If 1/0 = 0 sounds unusable to you, Pony's garbage collection scheme (which is brilliant, by the way) is going to make you think the language is insane.
I don't know, does it even matter? What happens when you try to divide a physical object into 0 parts? It doesn't create infinite pieces. It doesn't make the object disappear. Seems like nothing happened. Maybe when we divide by 0 in a program it should halt and catch fire?
I hate logical arguments, I get sucked in and start arguing all the positions.
That's assuming we had rounding error from a positive number, not a negative number. Of course, if you are concerned about rounding, you shouldn't be using integer arithmetic.
>1/(a number approaching 0) produces ever increasing integers.
No. It produces a bunch of 0s, except when the denominator is 1 (where it produces 1) or the denominator is -1 (where it produces -1). Unless you're using a language like Python, in which case it produces -1 for all negative denominators.
There are lots of situations where it makes sense to keep computing even if you suspect the input data is wrong. It's not really good practice to always be crashing. You need to decide how to handle the bad input on a case-by-case basis.
Sorry to be pedantic.
Floating point infinity is not equal to math infinity. Floating point infinity means there was overflow of the representation we are using, not that the number is larger than any known number.
> Adding zero + zero + zero infinite times does not equal 1.
Sometimes it does. That’s what an integral is.
For example Riemann integral is just limit of sums built on tagged partitions of a closed interval with largest sub-interval approaches zero. But no single sub-interval is equal to zero, their lengths just approach zero while being strictly positive values.
Calculus does not divide by zero, calculus explores what happens when we move to zero as close as we can and even closer.
Yes, certainly it is.
"You can't divide something 0 times and get any number. Adding zero + zero + zero infinite times does not equal 1."
The discussion is about mathematics, not elementary school arithmetic.
Generally, your viewpoint comes from an incorrect understanding of mathematics, so let's explore what math actually is:
When we say "10 / 2 = 5", the result "5" doesn't come out of nowhere. It comes out of the definition of division.
There are several ways you could define division. You could interpret "10 / 2 = 5" as meaning any of:
• "If you had a 10-inch stick and you divided it into 2 equal parts, each part would be 5 inches."
• "If you had the equation 2 * X = 10, X = 5 would be a solution to it."
• "If you had 10 Pa of pressure in an enclosed box, and you increased the volume of the box to 2 times its previous volume, its new pressure would be 5 Pa."
• "A wave of wavelength 2cm would have a frequency of 5 per 10cm."
These definitions all lead to the same result – in other words, they're equivalent. When this happens, mathematicians usually don't particularly care which one is the "real" definition.
This applies to many different mathematical axioms. For instance compare the definition of the Parallel Postulate on Wikipedia:
"If a line segment intersects two lines, the two lines will intersect on the side that their angles with the line segment sum up to less than 180°"
– https://en.wikipedia.org/wiki/Parallel_postulate
with the definition on Wolfram MathWorld:
"If you have a straight line and a point not on it, there exists only one straight line which passes through that point and never intersects the first line."
– http://mathworld.wolfram.com/ParallelPostulate.html
These are different definitions. But since they lead to the same result, mathematicians don't really care to argue over which is the "real" definition.
Some definitions only apply over a subset of numbers. For instance, originally, "5 - 10" was undefined. Then negative numbers were invented, to expand the definition. The same thing happened with square roots and complex numbers.
That's the same thing with division. 1 / 0 was originally undefined. But you can come up with new number systems that define it, while preserving all the other properties that make division what it is. A common definition is 1 / 0 = Infinity, which is done in the Riemann sphere number system:
https://en.wikipedia.org/wiki/Riemann_sphere
There's nothing mathematically incorrect about doing any of this.
I'm on the Pony core team. I will be writing in more detail about this decision. A few short notes until then:
1) no one on the team has ever been happy with ending up here, understanding why the decision was made involved understand how partial functions (one that can produce errors like division by zero) are handled in Pony and interesting ergonomic issues that can result that is a large part of what my post will be about.
2) this applies only to integer division wherein division by zero is undefined. 1.0/0.0 uses the available Infinity value.
3) Partial function math is coming to Pony that includes 1/0 as partial (ie error producing) as well as handling integer overflow and underflow for operations: `+`, `-`, and `*`.
4) It's very straightforward even without that those operations to define your own division that will be partial (ie return an error) for division by zero.
Edit to include link to the comment below because it contains a good bit of the decisions that have to make when dealing with integer math:
https://news.ycombinator.com/item?id=17736637
Which is part of what I will touch on in my post about the decision process that Pony went through to reach to state we are currently at (which I want to highlight, is one we intend to improve- see #3 above).