a *= b not equivalent to a = a*b
I've been playing with the binomial function, and found that in the below code, rs *= x does not behave the same way as rs = rs * x. When I set FAIL to True, I get a different result. Both results are below. I had read that the two were equivalent. What am I missing? thanks, -= miles =- #!/usr/bin/python2 import sys FAIL= True if len(sys.argv)>1 else False def bin(n,k): rs=1 k=min(k,n-k) for i in range(1,k+1): if FAIL: rs *= (n-(i-1))/i # these should be the same, else: rs = rs * (n-(i-1))/i # but apparently are not return rs for n in range(10): for k in range(n+1): print bin(n,k), print'' --- output - $ pascal2 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1 1 7 21 35 35 21 7 1 1 8 28 56 70 56 28 8 1 1 9 36 84 126 126 84 36 9 1 $ pascal2 fail 1 1 1 1 2 1 1 3 3 1 1 4 4 4 1 1 5 10 10 5 1 1 6 12 12 12 6 1 1 7 21 21 21 21 7 1 1 8 24 48 48 48 24 8 1 1 9 36 72 72 72 72 36 9 1 -- https://mail.python.org/mailman/listinfo/python-list
Re: a *= b not equivalent to a = a*b
Aha. That's interesting. On Friday, August 26, 2016 at 2:11:32 AM UTC-7, Peter Otten wrote: > mlz wrote: > > > Yes, I just worked that out. It's the integer math that's the problem. > > > > I guess this has been fixed in python 3, but unfortunately it seems that > > most people are still using python 2. > > Note that you can get Python 3's default behaviour in Python 2 with > > from __future__ import division > > at the beginning of the module. > > >>> 2/3 > 0 > >>> from __future__ import division > >>> 2/3 > 0. -- https://mail.python.org/mailman/listinfo/python-list
Re: a *= b not equivalent to a = a*b
Partly it's the layout, but mathematically speaking the two should be equal. (a*b)/c should equal a*(b/c) The fact that they're not is surprising, because python 2 so seamlessly supports big integers in a mathematically correct way. I consider such surprising behavior to be abstraction leak, which is probably why it has been fixed in python 3. -= m =- On Friday, August 26, 2016 at 12:54:02 AM UTC-7, Erik wrote: > On 26/08/16 08:14, mlz wrote: > > > > I was being facetious, but behind it is a serious point. Neither the APL > > nor the J languages use precedence even though their inventor, Ken Iverson, > > was a mathematician. > > > > That was to support functional programming dating back to the 1970's. > > Precedence is not the issue here anyway. Both '*' and '/' have the same > precedence. The two operations in your expressions have to be evaluated > in SOME order - either left-to-right or right-to-left. > > > The issue is twofold: > > Firstly, the compound assignments will always evaluate their RHS before > performing the assignment - this is not the same as operator precedence > - they have to, else what does Python pass to the function that knows > what the compound assignment means for that type (e.g. sequences may be > extended for '*=')? So for compound assignments there is always > effectively an implicit set of parentheses around the RHS compared to > the expression without the assignment operator (if you think of the > compound assignment as being a _part_ of the overall expression). > > Secondly, the way you have chosen to layout your code has fooled your > brain into thinking that the division is performed before the > multiplication. Python doesn't care that you jammed the sub-expression > together with no whitespace ;) > > E. -- https://mail.python.org/mailman/listinfo/python-list
Re: a *= b not equivalent to a = a*b
It's true that a*(b/c) yields fractions which would probably accrue accuracy errors depending on how those values are implemented. For example, it is possible to represent 1/3 internally as two numbers, numerator and denominator, thus avoiding the repeating decimal (or binimal, or whatever it's called). I believe there are languages that preserve exact accuracy in this way for rational fractions. I don't know if Python is one of them. On the other hand, (a*b)/c is safer since in this case (for the binomial coefficient) it always yields an integer. -= m =- On Friday, August 26, 2016 at 1:42:31 AM UTC-7, Christian Gollwitzer wrote: > Am 26.08.16 um 09:53 schrieb Erik: > > On 26/08/16 08:44, mlz wrote: > >> Here's the key: > >> > >> $ python2 > >> Python 2.7.10 ... > >>>>> 1/2 > >> 0 > >>>>> > >> > >> $ python > >> Python 3.5.1 ... > >>>>> 1/2 > >> 0.5 > >>>>> 1//2 > >> 0 > >>>>> > >> > >> I read about this awhile ago, but it's not until it bites you that you > >> remember fully. > > > > How is this related to your question? The example explicitly says Python > > 2 and doesn't use the '//' operator. > > > > It's related by the fact that a*b/c performs integer division (intended > by the OP) which gives a different result than a*(b/c) (unintended by > the OP). Floating point (as in Python 3) *also* may give a different > result, but the deviation from the "true", i.e. mathematical value, is > far less than with integer arithmetics. > > Christian -- https://mail.python.org/mailman/listinfo/python-list
