2 + 2 = 5

Discussion in 'Python' started by Paul Rubin, Jul 4, 2012.

  1. Paul Rubin

    Paul Rubin Guest

    I just came across this (https://gist.github.com/1208215):

    import sys
    import ctypes
    pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    five = ctypes.cast(id(5), pyint_p)
    print(2 + 2 == 5) # False
    five.contents[five.contents[:].index(5)] = 4
    print(2 + 2 == 5) # True (must be sufficiently large values of 2 there...)

    Heh. The author is apparently anonymous, I guess for good reason.
    Paul Rubin, Jul 4, 2012
    #1
    1. Advertising

  2. Paul Rubin, 04.07.2012 21:37:
    > I just came across this (https://gist.github.com/1208215):
    >
    > import sys
    > import ctypes
    > pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    > five = ctypes.cast(id(5), pyint_p)
    > print(2 + 2 == 5) # False
    > five.contents[five.contents[:].index(5)] = 4
    > print(2 + 2 == 5) # True (must be sufficiently large values of 2 there...)
    >
    > Heh. The author is apparently anonymous, I guess for good reason.


    That's not portable, though. ;)

    Stefan
    Stefan Behnel, Jul 4, 2012
    #2
    1. Advertising

  3. Paul Rubin

    Michael Ross Guest

    Am 04.07.2012, 21:37 Uhr, schrieb Paul Rubin <>:

    > I just came across this (https://gist.github.com/1208215):
    >
    > import sys
    > import ctypes
    > pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    > five = ctypes.cast(id(5), pyint_p)
    > print(2 + 2 == 5) # False
    > five.contents[five.contents[:].index(5)] = 4
    > print(2 + 2 == 5) # True (must be sufficiently large values of 2
    > there...)
    >
    > Heh. The author is apparently anonymous, I guess for good reason.



    Neat.

    Playing with it, i'm wondering:


    This:

    import sys
    import ctypes
    pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    five = ctypes.cast(id(5), pyint_p)
    five.contents[five.contents[:].index(5)] = 4

    print ( 2 + 2 == 5 )
    print 5
    print 5 - 2

    put into a script and run prints:

    True
    4
    3

    while entered at the python prompt it prints:

    True
    4
    2

    ??


    Regards,
    Michael
    Michael Ross, Jul 4, 2012
    #3
  4. On 04/07/2012 20:37, Paul Rubin wrote:
    > I just came across this (https://gist.github.com/1208215):
    >
    > import sys
    > import ctypes
    > pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    > five = ctypes.cast(id(5), pyint_p)
    > print(2 + 2 == 5) # False
    > five.contents[five.contents[:].index(5)] = 4
    > print(2 + 2 == 5) # True (must be sufficiently large values of 2 there...)
    >
    > Heh. The author is apparently anonymous, I guess for good reason.
    >


    The author got confused trying to switch from imperial to metric numbers
    or vice versa?

    --
    Cheers.

    Mark Lawrence.
    Mark Lawrence, Jul 4, 2012
    #4
  5. On 07/04/2012 09:37 PM, Paul Rubin wrote:
    > I just came across this (https://gist.github.com/1208215):
    >
    > import sys
    > import ctypes
    > pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    > five = ctypes.cast(id(5), pyint_p)
    > print(2 + 2 == 5) # False
    > five.contents[five.contents[:].index(5)] = 4
    > print(2 + 2 == 5) # True (must be sufficiently large values of 2 there...)
    >
    > Heh. The author is apparently anonymous, I guess for good reason.
    >


    I'm reminded of the swap(a,b) function I wrote a couple of years back.

    http://blog.jollybox.de/archives/62-python-swap
    Thomas Jollans, Jul 4, 2012
    #5
  6. Paul Rubin

    alex23 Guest

    On Jul 5, 5:37 am, Paul Rubin <> wrote:
    >     print(2 + 2 == 5) # True (must be sufficiently large values of 2 there...)


    I believe CCP use a variant of this approach in EvE with Stackless
    Python.
    alex23, Jul 5, 2012
    #6
  7. On 7/4/2012 14:37, Paul Rubin wrote:
    > I just came across this (https://gist.github.com/1208215):
    >
    > import sys
    > import ctypes
    > pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    > five = ctypes.cast(id(5), pyint_p)
    > print(2 + 2 == 5) # False
    > five.contents[five.contents[:].index(5)] = 4
    > print(2 + 2 == 5) # True (must be sufficiently large values of 2 there...)
    >
    > Heh. The author is apparently anonymous, I guess for good reason.


    Probably just nostalgic for old Fortran, which, supposedly, allowed you
    to change the values of literals by passing them to a function by
    reference and then modifying the value.

    Evan



    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.10 (MingW32)
    Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

    iQEcBAEBAgAGBQJP9OJBAAoJEAOzoR8eZTzgPyQH/RYRdhNWV7XjjAg4SgNjt3wj
    a0KSrKHg8TPKb2Sbj6M+t09UzE6dvwQMpUuO6oviue4pUgrPa9E0OK7TuWYi/3AA
    J5GoC8xoWuy1t9+7Zu/fBC5ikuwPmDNOLhP0WgPCCdS35EZbNPvVg7FpvsidXeYZ
    aFUFYi5VvJFmCPIGHFLqsomljMkavOde2ZtuPXSPgp4cBkb0sRxsMebN9xPjRWO9
    5Sb6hchtwYZznJpc19WWCMSnIY+Ug30jsdP09dlr8SQf+PalOyBJbM9BoSaQ9NCG
    ctFB/wDO6zamzr/Ba4vEA+9I6b4hsnjFe6l+1hlUgKBTxfbRqYoA4x6DGoz2Nb0=
    =MvhR
    -----END PGP SIGNATURE-----
    Evan Driscoll, Jul 5, 2012
    #7
  8. Paul Rubin

    Terry Reedy Guest

    On 7/4/2012 4:37 PM, Michael Ross wrote:
    > Am 04.07.2012, 21:37 Uhr, schrieb Paul Rubin <>:
    >
    >> I just came across this (https://gist.github.com/1208215):
    >>
    >> import sys
    >> import ctypes
    >> pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    >> five = ctypes.cast(id(5), pyint_p)
    >> print(2 + 2 == 5) # False
    >> five.contents[five.contents[:].index(5)] = 4
    >> print(2 + 2 == 5) # True (must be sufficiently large values of 2
    >> there...)
    >>
    >> Heh. The author is apparently anonymous, I guess for good reason.

    >
    >
    > Neat.
    >
    > Playing with it, i'm wondering:
    >
    >
    > This:
    >
    > import sys
    > import ctypes
    > pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    > five = ctypes.cast(id(5), pyint_p)
    > five.contents[five.contents[:].index(5)] = 4
    >
    > print ( 2 + 2 == 5 )
    > print 5
    > print 5 - 2
    >
    > put into a script and run prints:
    >
    > True
    > 4
    > 3


    The compile-time optimizer computed the contant 5-2 in C.

    > while entered at the python prompt it prints:
    >
    > True
    > 4
    > 2


    It must not run for interactive input with the undisclosed version you
    are running.

    If I run the script in 3.3 Idle, I get the same output you got. If I
    then enter '5-2' interactively, I still get 3. Maybe the constant folder
    is always on now.

    --
    Terry Jan Reedy
    Terry Reedy, Jul 5, 2012
    #8
  9. On Wed, 04 Jul 2012 23:38:17 -0400, Terry Reedy wrote:

    > If I run the script in 3.3 Idle, I get the same output you got. If I
    > then enter '5-2' interactively, I still get 3. Maybe the constant folder
    > is always on now.


    Yes, I believe constant folding is always on, since Python 2.4 if I
    remember correctly. Somebody who cares more than me can possibly check
    the "What's New" documents :)


    --
    Steven
    Steven D'Aprano, Jul 5, 2012
    #9
  10. Paul Rubin

    Hans Mulder Guest

    On 5/07/12 07:32:48, Steven D'Aprano wrote:
    > On Wed, 04 Jul 2012 23:38:17 -0400, Terry Reedy wrote:
    >
    >> If I run the script in 3.3 Idle, I get the same output you got. If I
    >> then enter '5-2' interactively, I still get 3. Maybe the constant folder
    >> is always on now.

    >
    > Yes, I believe constant folding is always on, since Python 2.4 if I
    > remember correctly. Somebody who cares more than me can possibly check
    > the "What's New" documents :)


    It's not a difference between 2.4 and 3.3; the difference is between
    Idle and the command-line version of the interactive interpreter.

    If I type the same code into Idle and the interactive interpreter
    (both using 3.3alpha1), I get 3 in Idle and 2 in Terminal.

    I don't quite understand why this difference exists.


    Confused,

    -- HansM
    Hans Mulder, Jul 5, 2012
    #10
  11. Paul Rubin

    Laszlo Nagy Guest

    On 2012-07-04 21:37, Paul Rubin wrote:
    > I just came across this (https://gist.github.com/1208215):
    >
    > import sys
    > import ctypes
    > pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    > five = ctypes.cast(id(5), pyint_p)
    > print(2 + 2 == 5) # False
    > five.contents[five.contents[:].index(5)] = 4
    > print(2 + 2 == 5) # True (must be sufficiently large values of 2 there...)
    >
    > Heh. The author is apparently anonymous, I guess for good reason.


    >>> five.contents[five.contents[:].index(5)] = 4
    >>> 5

    4
    >>> 5 is 4

    True

    But this I don't understand:

    >>> 5+0

    4
    >>> 5+1

    4
    >>> 5+2

    6
    Laszlo Nagy, Jul 5, 2012
    #11
  12. Paul Rubin

    MRAB Guest

    On 05/07/2012 15:34, Laszlo Nagy wrote:
    > On 2012-07-04 21:37, Paul Rubin wrote:
    >> I just came across this (https://gist.github.com/1208215):
    >>
    >> import sys
    >> import ctypes
    >> pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    >> five = ctypes.cast(id(5), pyint_p)
    >> print(2 + 2 == 5) # False
    >> five.contents[five.contents[:].index(5)] = 4
    >> print(2 + 2 == 5) # True (must be sufficiently large values of 2 there...)
    >>
    >> Heh. The author is apparently anonymous, I guess for good reason.

    >
    > >>> five.contents[five.contents[:].index(5)] = 4
    > >>> 5

    > 4
    > >>> 5 is 4

    > True
    >
    > But this I don't understand:
    >
    > >>> 5+0

    > 4


    5 is interned as 4, 0 is interned as 0, 4+0 is calculated as 4 and then
    interned as 4.

    > >>> 5+1

    > 4


    5 is interned as 4, 1 is interned as 1, 4+1 is calculated as 5 and then
    interned as 4.

    > >>> 5+2

    > 6
    >

    5 is interned as 4, 2 is interned as 2, 4+2 is calculated as 6 and then
    interned and 6.

    Simple really! :)
    MRAB, Jul 5, 2012
    #12
  13. On Thu, Jul 5, 2012 at 10:34 AM, Laszlo Nagy <> wrote:
    >>>> 5+1

    > 4


    4 + 1 is 5 is 4.

    (e.g. try 2+3 as well).

    -- Devin
    Devin Jeanpierre, Jul 5, 2012
    #13
  14. On Thu, 05 Jul 2012 15:57:53 +0200, Hans Mulder wrote:

    > On 5/07/12 07:32:48, Steven D'Aprano wrote:
    >> On Wed, 04 Jul 2012 23:38:17 -0400, Terry Reedy wrote:
    >>
    >>> If I run the script in 3.3 Idle, I get the same output you got. If I
    >>> then enter '5-2' interactively, I still get 3. Maybe the constant
    >>> folder is always on now.

    >>
    >> Yes, I believe constant folding is always on, since Python 2.4 if I
    >> remember correctly. Somebody who cares more than me can possibly check
    >> the "What's New" documents :)

    >
    > It's not a difference between 2.4 and 3.3; the difference is between
    > Idle and the command-line version of the interactive interpreter.
    >
    > If I type the same code into Idle and the interactive interpreter (both
    > using 3.3alpha1), I get 3 in Idle and 2 in Terminal.
    >
    > I don't quite understand why this difference exists.


    This difference exists because you are mucking about with implementation
    details of Python, changing things which are not guaranteed by the
    language, in ways that you are not supposed to change them. Since
    changing the value of the int 2 into that of 3 is not supported, you can
    hardly expect consistent behaviour. You're lucky that you don't get a
    segfault. (In fact, if you keep playing around with it, you likely will
    get a segfault.)

    Idle does many things differently to the basic Python interpreter. This
    should not surprise you. You should be surprised if it *does* work the
    same in Idle and the basic Python interpreter.



    --
    Steven
    Steven D'Aprano, Jul 5, 2012
    #14
  15. On 05.07.2012 16:34, Laszlo Nagy wrote:
    >>>> five.contents[five.contents[:].index(5)] = 4
    >>>> 5

    > 4
    >>>> 5 is 4

    > True


    That's surprising, because even after changing 5 to 4 both objects still
    have different id()s (tested on Py2.7), so 5 is 4 /should/ still be
    False (But isn't on my 2.7). But that's some implementation detail we
    are not supposed to play with ;)

    > But this I don't understand:
    >
    >>>> 5+0

    > 4
    >>>> 5+1

    > 4
    >>>> 5+2

    > 6


    That's easy:

    5+0 is actually 4+0, because 5 == 4, so 5+0 gives 4.
    5+1 is actually 4+1, which is 5, but 5 is again 4.
    5+2 is 4+2 which is 6.

    Greetings
    Alexander Blinne, Jul 5, 2012
    #15
  16. Paul Rubin

    Hans Mulder Guest

    On 5/07/12 19:03:57, Alexander Blinne wrote:
    > On 05.07.2012 16:34, Laszlo Nagy wrote:
    >>>>> five.contents[five.contents[:].index(5)] = 4
    >>>>> 5

    >> 4
    >>>>> 5 is 4

    >> True


    > That's surprising, because even after changing 5 to 4 both objects still
    > have different id()s (tested on Py2.7), so 5 is 4 /should/ still be
    > False (But isn't on my 2.7). But that's some implementation detail we
    > are not supposed to play with ;)


    On my 2.7, id(5) gives the same value as id(4) == id(2+2), but id(2+3)
    has a different value. The 'is' operator is consistent with 'id':

    >>> 4 is 5

    True
    >>> 2+2 is 2+3

    False

    This is when using the interactive interpreter; it may be different
    in Idle.

    -- HansM
    Hans Mulder, Jul 5, 2012
    #16
  17. Re: Re: 2 + 2 = 5

    On 01/-10/-28163 01:59 PM, Alexander Blinne wrote:
    > 5+0 is actually 4+0, because 5 == 4, so 5+0 gives 4.
    > 5+1 is actually 4+1, which is 5, but 5 is again 4.
    > 5+2 is 4+2 which is 6.


    Now all I can think is "Hoory for new math, new-hoo-hoo math" :)

    Evan
    Evan Driscoll, Jul 5, 2012
    #17
  18. On 05/07/2012 22:46, Evan Driscoll wrote:
    > On 01/-10/-28163 01:59 PM, Alexander Blinne wrote:
    >> 5+0 is actually 4+0, because 5 == 4, so 5+0 gives 4.
    >> 5+1 is actually 4+1, which is 5, but 5 is again 4.
    >> 5+2 is 4+2 which is 6.

    >
    > Now all I can think is "Hoory for new math, new-hoo-hoo math" :)
    >
    > Evan


    It wont do you a bit of good to read new math!

    (My mind was on exactly the same track)

    ~Andrew
    Andrew Cooper, Jul 5, 2012
    #18
  19. On Thu, 05 Jul 2012 16:46:48 -0500, Evan Driscoll wrote:

    > On 01/-10/-28163 01:59 PM, Alexander Blinne wrote:
    >> 5+0 is actually 4+0, because 5 == 4, so 5+0 gives 4. 5+1 is actually
    >> 4+1, which is 5, but 5 is again 4. 5+2 is 4+2 which is 6.

    >
    > Now all I can think is "Hoory for new math, new-hoo-hoo math" :)


    +1 QOTW



    --
    Steven
    Steven D'Aprano, Jul 6, 2012
    #19
  20. Paul Rubin

    Guest

    On Friday, July 6, 2012 8:39:58 AM UTC+10, Andrew Cooper wrote:
    > On 05/07/2012 22:46, Evan Driscoll wrote:
    > &gt; On 01/-10/-28163 01:59 PM, Alexander Blinne wrote:
    > &gt;&gt; 5+0 is actually 4+0, because 5 == 4, so 5+0 gives 4.
    > &gt;&gt; 5+1 is actually 4+1, which is 5, but 5 is again 4.
    > &gt;&gt; 5+2 is 4+2 which is 6.
    > &gt;
    > &gt; Now all I can think is &quot;Hoory for new math, new-hoo-hoo math&quot; :)
    > &gt;
    > &gt; Evan
    >
    > It wont do you a bit of good to read new math!
    >
    > (My mind was on exactly the same track)
    >
    > ~Andrew


    +1
    , Jul 15, 2012
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page