tag:blogger.com,1999:blog-8699431508730375743.post7023294333989359916..comments2014-08-28T12:15:36.772-07:00Comments on The History of Python: Why Python's Integer Division FloorsGuido van Rossumhttp://www.blogger.com/profile/12821714508588242516noreply@blogger.comBlogger14125tag:blogger.com,1999:blog-8699431508730375743.post-38321027778153819462014-06-29T07:07:18.672-07:002014-06-29T07:07:18.672-07:00@Dobes: "The normal rules of algebra" is...@Dobes: "The normal rules of algebra" is an ill-defined phrase when discussing integer division. The integers are a ring not a field.<br /><br />Associativity breaks for any implementation of integer division. Consider (5 + 1)//2 vs. 5//2 + 1//2<br /><br />The fact that there is one special case when associativity works the way someone might naively expect in C when in general the "normal rules of algebra" are disobeyed, is not really an advantage of C. There is practically no conceivable situation in which you would want associativity exactly for the case of inverses. However, there is certainly a conceivable case where you'd hope it would break: i.e. if you happen to think of a test case that only tests for associativity with inverses. Whatever code included your mistaken notion of how division should associate in C would have been a lot harder to debug than it is in a language like Python when it "breaks" for the obvious test case just as much as it does for all sorts of real scenarios.<br /><br />Floats on the other hand... well, the original implementation is so screwed up that it's not salvageable. If there were a few invisible trailing bits that got computed with addition and multiplication, but were ignored with comparisons,or if they had been designed to behave like a field, you could say without any reservation that Python's implementation is wrong and that C's implementation is right. As things stand, they're both wrong, and C/javascript's implementation is probably slightly less wrong for floats.<br /><br />Python's implementation for ints is the correct one. It respects the rules of mathematics much more thoroughly than C's because, unlike integer division, the modulo operation does have well-defined algebraic properties.<br /><br />When you are dealing with the field that is the natural numbers modulo 7, for example, is always correct under Pythons implementation; whereas, it is correct only as long as your values are positive for C's, which never happens because C's implementation returns negative integers even if all of the ones you started with were positive. grr, (I've seen numerous non-theoretical use-cases for why you would want this. The most obvious have to do with positioning graphical components or with ABCDEFG testing -- a faster way of doing AB testing.)<br /><br />If you take a closer look at the list you linked to, you will notice that every language that was designed by people who really care about math has an operator either called "mod" or called "%" that does exactly the same thing as Python's implementation. There is some mixture among the quick and dirtier hacker languages. (All the languages with math in their name, Haskell, OCaml, Common Lisp, SML, R, Clojure, maple goes a step further). Every programming language I've ever heard of a mathematician actually using does it this way. Certainly all of the programming languages that mathematicians have written.<br /><br />If you are writing your own programming language and you want to decide how to implement integer division, please stick with the way that all of the mathematicians use. There are very good reasons why they have decided that one particular implementation and not the other is correct.left blankhttp://www.blogger.com/profile/06453595790575475693noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-24590303827479647062013-08-30T14:04:03.233-07:002013-08-30T14:04:03.233-07:00Float representation is horrible everywhere. And ....Float representation is horrible everywhere. And .1+.2 is not .3 almost everywhere.Vekyhttp://www.blogger.com/profile/12207072339468136950noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-78139270764898269342013-06-03T10:06:40.041-07:002013-06-03T10:06:40.041-07:00Just crap and a very bad decision. Just like 0.1 +...Just crap and a very bad decision. Just like 0.1 + 0.2 is not 0.3 in python. Float representation is -horrible- in python. May be "mathematically" correct, it doesn't make sense to 99% of people and just bugs 99% of people, no matter what you explain hereGeerthttp://www.blogger.com/profile/09493937775290125048noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-51603440956925115252013-04-16T13:43:23.269-07:002013-04-16T13:43:23.269-07:00@Dobes: indeed. Also note that Python's appro...@Dobes: indeed. Also note that Python's approach is not ideal when generalized to floats. Tim Peters was the first to point this out to me.Guido van Rossumhttp://www.blogger.com/profile/12821714508588242516noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-71142927909217684902013-04-16T12:56:10.072-07:002013-04-16T12:56:10.072-07:00For the benefit of those wondering which approach ...For the benefit of those wondering which approach to take for their own programming language, consider that there are cases where the floor integer division doesn't obey the normal rules of algebra as well as truncating integer division; some apparently equivalent expressions will give different results:<br /><br />-5//2 * -1 == -2, but -1 * -5 // 2 == -3.<br /><br />-5//2 + 5//2 == -1, but (-5 + 5)//2 == 0.<br /><br />So, don't be afraid to adopt the same approach as C, Javascript, and so on worrying that it's less correct or more error prone. Probably neither approach is really "better", it's just a matter of preference.<br /><br />See http://en.wikipedia.org/wiki/Modulo_operation for a list of programming languages and how they chose to do integer division.<br />Dobeshttp://www.blogger.com/profile/09392777569321223496noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-55232304189922686162013-01-24T14:52:59.310-08:002013-01-24T14:52:59.310-08:00It might be worth noting, that divmod for Decimal ...It might be worth noting, that divmod for Decimal behaves different than divmod for int / float when used with negative numbers.gweishttp://www.blogger.com/profile/18130135988470868703noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-53940272477009643862011-03-17T10:57:42.077-07:002011-03-17T10:57:42.077-07:00Not to argue that this was a bad decision, but I j...Not to argue that this was a bad decision, but I just wanted to report that this bit me when trying to convert integral cents into dollars and cents. cents%100, cents/100 is a construct I learned in my very early days of programming. It didn't occur to me that this wouldn't work in python, but it blew up rather spectacularly with negative amounts.<br /><br />Now, the Python standard library also has the very excellent Decimal class, which is what we use internally to represent all money amounts. So the fix was to simply construct the Decimal, than divide it by 100, which is a shorter and cleaner code. So, the story has a very happy ending =)Kurt Rosehttp://www.blogger.com/profile/11161604109056835253noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-60618345481871963022010-08-25T05:25:34.247-07:002010-08-25T05:25:34.247-07:00The CDC behavior of 60 1's being negative zero...The CDC behavior of 60 1's being negative zero indicates one's complement representation, not sign magnitude. Ah, the days of the Cyber-70!Eric Smithhttp://www.blogger.com/profile/10688478385136141066noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-66633626947137341562010-08-24T15:53:40.421-07:002010-08-24T15:53:40.421-07:00Thanks a lot for this answer =]
Finally I'll b...Thanks a lot for this answer =]<br />Finally I'll be able to stop wondering why Python integer division was implemented that way.<br />But now, I owe WapiFlapi a cookie...Lassihttp://www.blogger.com/profile/07184206798470017971noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-51828507824024379722010-08-24T13:05:04.192-07:002010-08-24T13:05:04.192-07:00Thanks Twitterers @dgou and @schuetzdj for reporti...Thanks Twitterers @dgou and @schuetzdj for reporting a text mistake; I've fixed it now!Guido van Rossumhttp://www.blogger.com/profile/12821714508588242516noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-90320578446267333082010-08-24T12:49:37.445-07:002010-08-24T12:49:37.445-07:00Thanks a lot for taking the time to answer this :)...Thanks a lot for taking the time to answer this :)<br />Now everyone on the IRC channel owns me a cookie !<br /><br />And the explanation is very interesting, never thought about it this way before.Wapi Flapihttp://www.blogger.com/profile/06109630763850315098noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-59762791806193897202010-08-24T11:40:13.272-07:002010-08-24T11:40:13.272-07:00LOL - it's wonderfully ironic that the comment...LOL - it's wonderfully ironic that the commenting system destroyed the whitespace in my Python code snippet :-)Tim Petershttp://www.blogger.com/profile/15023674227978538137noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-19445284626986810362010-08-24T11:39:27.076-07:002010-08-24T11:39:27.076-07:00Should note that C Classic didn't define the s...Should note that C Classic didn't define the sign of the result, but did require that<br /><br />a == (a/b)*b + a%b<br /><br />hold whenever a/b was representable. Not one C programmer in a million knew that, though ;-) C99 finally did insist on giving the wrong answer, seemingly just to be compatible with FORTRAN.<br /><br />I've never seen an integer use case where the wrong answer was helpful. Use cases where the right answer are helpful abound. For example, when trading equity options the 3rd Friday of the month is a crucial date, and<br /><br />import datetime<br />FRIDAY = 4<br /># Return date of third Friday of month.<br />def fri3(year, month):<br /> d = datetime.date(year, month, 1)<br /> diff = (FRIDAY - d.weekday()) % 7 + 14<br /> return d + datetime.timedelta(days=diff)<br /><br />is screamingly natural. Weekdays, hours on a 24-clock, minutes, seconds, months in a year, year numbers in a century ... many things related to time are naturally represented by the ordinals in range(N) for some N, repeated endlessly. Using the right definition of % allows uniform code to move forward or backward in such sequences.<br /><br />But for floats it's usually most useful to have<br /><br /> 0 <= a%b <= abs(b/2)<br /><br />and damn the signs. The mathematical result is exactly representable (ark's point) under that constraint too, and it caters to that floating mod is most often used for range reduction (so that it's helpful for the result to have the smallest absolute value possible).<br /><br />The integers are a subset of the reals in math, but that has nothing to do with floats ;-)Tim Petershttp://www.blogger.com/profile/15023674227978538137noreply@blogger.comtag:blogger.com,1999:blog-8699431508730375743.post-82822862976624106462010-08-24T10:09:30.335-07:002010-08-24T10:09:30.335-07:00Tim is right to be worried about extending the tru...Tim is right to be worried about extending the truncate-toward-negative-infinity rule to floating-point numbers. The reason is that if a%b always has the sign of a when a's and b's signs differ, then a%b can always be represented exactly as a floating-point number if a and b can be represented exactly--at least, in every floating-point representation system I've seen. If, however, a%b takes on the sign of b when the signs differ, there are values of a and b that can preclude a%b from being represented exactly.arkhttp://www.blogger.com/profile/18246896789315209359noreply@blogger.com