4 ms·
Hi, 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 w
by spooneybarger 8y ago
Hi,
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 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).
- thanatos_dem 8y ago> 2) this applies only to integer division wherein division by zero is undefined. 1.0/0.0 uses the available Infinity value. 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.
- spooneybarger 8y agoHillel is talking about math. Unfortunately computers don't really do "math". For example, math doesn't have overflow and underflow to deal with. 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.
- starmole 8y agoIntegers are perfectly fine in math. But they are not a field. Integers modulo something are also well understood in math - but again not a field.
- nanimo 8y agoUnderflow and overflow and 2's complement are all just modular arithmetic, which is definitely math.
- gowld 8y agoComputers is the math you get, not the math you want.
- spooneybarger 8y agoHere's another good one for you... 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.
- std_throwaway 8y agoDid you mean 2/3?
- spooneybarger 8y agoNo. But most programming languages I know of return different results for 2/3 vs 2.0/3.0.
- jshap70 8y ago`3/2 = 1` is a consistent answer as long as the programmer understands modulo. The way you're phrasing it makes it sound like there are languages out there that say "`3/2 = 2` because 1.5 rounds up to 2". just so long as you don't expect a consistent answer between python2.7 and 3.x... >.>
- Zarel 8y agoThe phrasing is relatively clear to me as saying that some languages say 3/2 = 1.5 (e.g. JavaScript) and some languages say 3/2 = 1 (e.g. C).
- daveFNbuck 8y agoAs pointed out by others, floats work differently from ints in programming languages. Division in ints is usually defined such that if x = d * y + m, x / y = d and x % y = m. You can make this work by choosing the right m for every d, but when y is not 0, there are a few conventions you can choose to pick a sensible d and m. When y = 0, the m = a and d is completely free, so there really isn't a right answer from how division works. 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.
- jlouis 8y agoIn the mathematical sense, a Field is a Commutative Ring with the added constraint that the multiplicative operation has inverses for every non-zero element. 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.
- ArtWomb 8y agoHaving 1/0 = 0 and 1.0f / 0.0f = +inf makes sense in two applications I can think of. The first would be currency systems in which prices down to the pre-determined fractional component are represented as unsigned integers. In calculating margin requirements division by zero equating to zero would be the correct answer. And two, for double precision continuous variables, any application involving 3D geometrical transforms. An aspect ratio approaching zero in one axis, would approach positive infinity in the other. 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!
- spooneybarger 8y agoWe are over in #ponylang on freenode if you ever want to stop by and chat.
- behringer 8y ago1/0 is not infinity either...
- spooneybarger 8y agobut with floating point units, 1.0/0.0 is infinity.
- behringer 8y agoThat's not correct mathematically though. You can't divide something 0 times and get any number. Adding zero + zero + zero infinite times does not equal 1.
- jibal 8y ago"That's not correct mathematically though." 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.
- behringer 8y agoFeel free to give me a proof that adds zeros and gets a number greater than 0.
- Zarel 8y agoIt's plenty correct mathematically; the linked article even explains this. 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 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 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 https://en.wikipedia.org/wiki/Riemann_sphere There's nothing mathematically incorrect about doing any of this.
- simonbyrne 8y agoWhat about I64.min_value() / (-1)? Why does that give 0? If you're doing wrap-around arithmetic it should give I64.min_value(). https://tio.run/##K8jPq/z/PzG5JL9IwTcxM49LAQjyUssVkotSE0tSNVLzyqwUXPPKNBVs7cByOaklChUKtgqeZiZ6uZl58WWJOaWpGpoK@goauoaaYCVAPXr5pSV6BUWZeSUaFXrFJUBGuoam5v//AA https://tio.run/##K8jPq/z/PzG5JL9IwTcxM49LAQjyUssVkotSE0tSNV...
- spooneybarger 8y agoThat might be an LLVM bug. `I64.max_value() + 1` gives the expected result. I'm going to have to look into that. Thanks.
- simonbyrne 8y agoApologies, I realise my comment was a bit snarky. Pony looks like a really neat language: I'll be interested to see what you do with it. Unfortunately LLVM considers division overflow undefined: http://llvm.org/docs/LangRef.html#id109 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 https://github.com/JuliaLang/julia/issues/8188
- spooneybarger 8y agoI didn't take it as snarky. I was genuinely surprised. Thank you. If you intended it to be snarky, I didn't notice. And thank you for the additional info, I've updated the issue I opened accordingly: https://github.com/ponylang/ponyc/issues/2858 https://github.com/ponylang/ponyc/issues/2858
- mcguire 8y agoI'd like to jump in here and point out that Pony ergonomics are unlike that if any other language; it is significantly different from any other language. 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.
- starmole 8y agoThis should be the top comment. INTEGERS are not a field. But that kind of makes the 0 choice worse? Even cpus always throw on integer divide by 0, so i don't really see the low level optimization. Does it enable some higher level optimization? Why not x/0 = x?
- saudioger 8y agothanks for such a ginuwine response
- ummonk 8y ago>2) this applies only to integer division wherein division by zero is undefined. 1.0/0.0 uses the available Infinity value. 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.
- js8 8y agoAs an aside, I have thought recently that integers should also have NaN value, just like floating point values have. It's useful in statistics to differentiate between not having a value and value of 0. 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.
- bluecalm 8y agoI like the idea of having integer NaN but I think unsigned numbers are problematic as there isn't any convenient way to encode it.