Division oddity

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Tim Rowe

    Division oddity

    If I do from __future__ import division then eval(1/2) gives me 0.5 as
    expected. But if I do print input("enter a sum: ") and enter 1/2 as
    the sum I get 0 as if I hadn't done the import. I thought input was
    supposed to give the same behaviour as an eval on raw input -- why the
    difference here?
  • Denis Sarrazin

    #2
    Re: Division oddity

    Try 1.0/2 instead of 1/2. Note that when I do eval("1/2") I get 0 not
    0.5

    -Denis

    Le Sun, 11 Jan 2004 23:45:48 +0000, Tim Rowe
    <tim@remove_if_ not_spam.digiti g.co.uk> a écrit :
    [color=blue]
    >If I do from __future__ import division then eval(1/2) gives me 0.5 as
    >expected. But if I do print input("enter a sum: ") and enter 1/2 as
    >the sum I get 0 as if I hadn't done the import. I thought input was
    >supposed to give the same behaviour as an eval on raw input -- why the
    >difference here?[/color]

    Comment

    • Jason Mobarak

      #3
      Re: Division oddity

      Denis Sarrazin wrote:[color=blue]
      > Try 1.0/2 instead of 1/2. Note that when I do eval("1/2") I get 0 not
      > 0.5[/color]

      Please note: "from __future__ import division", see PEP 238 which
      changes the behavior of the divisino operator.

      My results with Python 2.3.3:
      [color=blue][color=green][color=darkred]
      >>> from __future__ import division
      >>> eval('1/2')[/color][/color][/color]
      0.5[color=blue][color=green][color=darkred]
      >>> input()[/color][/color][/color]
      1/2
      0[color=blue][color=green][color=darkred]
      >>> eval(raw_input( ))[/color][/color][/color]
      1/2
      0.5
      [color=blue]
      >
      > -Denis
      >
      > Le Sun, 11 Jan 2004 23:45:48 +0000, Tim Rowe
      > <tim@remove_if_ not_spam.digiti g.co.uk> a écrit :
      >
      >[color=green]
      >>If I do from __future__ import division then eval(1/2) gives me 0.5 as
      >>expected. But if I do print input("enter a sum: ") and enter 1/2 as
      >>the sum I get 0 as if I hadn't done the import. I thought input was
      >>supposed to give the same behaviour as an eval on raw input -- why the
      >>difference here?[/color]
      >
      >[/color]

      Comment

      • Paul Rubin

        #4
        Re: Division oddity

        Tim Rowe <tim@remove_if_ not_spam.digiti g.co.uk> writes:[color=blue]
        > If I do from __future__ import division then eval(1/2) gives me 0.5 as
        > expected. But if I do print input("enter a sum: ") and enter 1/2 as
        > the sum I get 0 as if I hadn't done the import. I thought input was
        > supposed to give the same behaviour as an eval on raw input -- why the
        > difference here?[/color]

        The input function is calling eval from the context of the module
        where 'input' itself is defined. If you use "from __future__ import
        division" in module A and have "print 3/2" in module B, the value of
        3/2 in module B shouldn't be affected by the input, since module B
        may depend on integer division having the old behavior.

        The result is a little bit surprising at first glance though, so it
        should probably be documented.

        Comment

        • Robin Becker

          #5
          Re: Division oddity

          In article <7xeku5vrn8.fsf @ruckus.brouhah a.com>, Paul Rubin <http@?.cx>
          writes[color=blue]
          >Tim Rowe <tim@remove_if_ not_spam.digiti g.co.uk> writes:[color=green]
          >> If I do from __future__ import division then eval(1/2) gives me 0.5 as
          >> expected. But if I do print input("enter a sum: ") and enter 1/2 as
          >> the sum I get 0 as if I hadn't done the import. I thought input was
          >> supposed to give the same behaviour as an eval on raw input -- why the
          >> difference here?[/color]
          >
          >The input function is calling eval from the context of the module
          >where 'input' itself is defined. If you use "from __future__ import
          >division" in module A and have "print 3/2" in module B, the value of
          >3/2 in module B shouldn't be affected by the input, since module B
          >may depend on integer division having the old behavior.
          >
          >The result is a little bit surprising at first glance though, so it
          >should probably be documented.[/color]
          I get this in pythonwin with 2.3.2

          PythonWin 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)]
          on win32.
          Portions Copyright 1994-2001 Mark Hammond (mhammond@skipp inet.com.au) -
          see 'Help/About PythonWin' for further copyright information.[color=blue][color=green][color=darkred]
          >>> from __future__ import division
          >>> eval('1/2')[/color][/color][/color]
          0.5[color=blue][color=green][color=darkred]
          >>>[/color][/color][/color]

          In python I get


          Python 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on
          win32
          Type "help", "copyright" , "credits" or "license" for more information.[color=blue][color=green][color=darkred]
          >>> from __future__ import division
          >>> eval('1/2')[/color][/color][/color]
          0.5[color=blue][color=green][color=darkred]
          >>>[/color][/color][/color]

          so I guess pythonwin is broken in this respect.
          --
          Robin Becker

          Comment

          • Raymond Hettinger

            #6
            Re: Division oddity

            [Tim Rowe][color=blue][color=green]
            > > If I do from __future__ import division then eval(1/2) gives me 0.5 as
            > > expected. But if I do print input("enter a sum: ") and enter 1/2 as
            > > the sum I get 0 as if I hadn't done the import. I thought input was
            > > supposed to give the same behaviour as an eval on raw input -- why the
            > > difference here?[/color][/color]

            [Paul Rubin[[color=blue]
            > The input function is calling eval from the context of the module
            > where 'input' itself is defined. If you use "from __future__ import
            > division" in module A and have "print 3/2" in module B, the value of
            > 3/2 in module B shouldn't be affected by the input, since module B
            > may depend on integer division having the old behavior.[/color]

            Right!

            So, the way to get eval() to respond to the import is to pass along
            the current environment:
            [color=blue][color=green][color=darkred]
            >>> from __future__ import division
            >>> eval('9/2', globals())[/color][/color][/color]
            4.5


            Raymond Hettinger

            Comment

            • Paul Rubin

              #7
              Re: Division oddity

              Robin Becker <robin@jessikat .fsnet.co.uk> writes:[color=blue]
              > Python 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on
              > win32
              > Type "help", "copyright" , "credits" or "license" for more information.[color=green][color=darkred]
              > >>> from __future__ import division
              > >>> eval('1/2')[/color][/color]
              > 0.5[color=green][color=darkred]
              > >>>[/color][/color]
              >
              > so I guess pythonwin is broken in this respect.[/color]

              Huh? you get the expected result with both python and pythonwin. Neither
              one is broken. The surprising result is from input(), not eval():

              $ python
              Python 2.2.2 (#1, Feb 24 2003, 19:13:11)
              [GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-4)] on linux2
              Type "help", "copyright" , "credits" or "license" for more information.[color=blue][color=green][color=darkred]
              >>> from __future__ import division
              >>> print input('expressi on: ')[/color][/color][/color]
              expression: 1/2
              0[color=blue][color=green][color=darkred]
              >>> print eval('1/2')[/color][/color][/color]
              0.5[color=blue][color=green][color=darkred]
              >>>[/color][/color][/color]

              That's because input evaluates its string in the context of a
              different module which was compiled with old-style division. I don't
              know of other functions that use eval like that, and input() should
              be deprecated or eliminated anyway, so this isn't a big deal.

              Comment

              • Denis Sarrazin

                #8
                Re: Division oddity

                Thanks. I'd not realized that we could test out new changes to Python
                within existing Python code. Cool.

                -D

                Le Mon, 12 Jan 2004 02:49:45 -0700, Jason Mobarak <jmob@unm.edu > a
                écrit :
                [color=blue]
                >Please note: "from __future__ import division", see PEP 238 which
                >changes the behavior of the divisino operator.[/color]


                Comment

                • Michael Hudson

                  #9
                  Re: Division oddity

                  python@rcn.com (Raymond Hettinger) writes:
                  [color=blue]
                  > [Tim Rowe][color=green][color=darkred]
                  > > > If I do from __future__ import division then eval(1/2) gives me 0.5 as
                  > > > expected. But if I do print input("enter a sum: ") and enter 1/2 as
                  > > > the sum I get 0 as if I hadn't done the import. I thought input was
                  > > > supposed to give the same behaviour as an eval on raw input -- why the
                  > > > difference here?[/color][/color]
                  >
                  > [Paul Rubin[[color=green]
                  > > The input function is calling eval from the context of the module
                  > > where 'input' itself is defined. If you use "from __future__ import
                  > > division" in module A and have "print 3/2" in module B, the value of
                  > > 3/2 in module B shouldn't be affected by the input, since module B
                  > > may depend on integer division having the old behavior.[/color]
                  >
                  > Right!
                  >
                  > So, the way to get eval() to respond to the import is to pass along
                  > the current environment:
                  >[color=green][color=darkred]
                  > >>> from __future__ import division
                  > >>> eval('9/2', globals())[/color][/color]
                  > 4.5[/color]

                  Um, that's not how it works. Off the top of my head I'm not entirely
                  sure why eval() respects future statements and input() does not, but
                  it's probably easy enough to fix, if anyone cares (I don't think I
                  do).

                  Cheers,
                  mwh

                  --
                  Windows 2000: Smaller cow. Just as much crap. -- Jim's pedigree of
                  operating systems, asr

                  Comment

                  • Robin Becker

                    #10
                    Re: Division oddity

                    In article <7xbrp9h4xs.fsf @ruckus.brouhah a.com>, Paul Rubin <http@?.cx>
                    writes[color=blue]
                    >Robin Becker <robin@jessikat .fsnet.co.uk> writes:[color=green]
                    >> Python 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on
                    >> win32
                    >> Type "help", "copyright" , "credits" or "license" for more information.[color=darkred]
                    >> >>> from __future__ import division
                    >> >>> eval('1/2')[/color]
                    >> 0.5[color=darkred]
                    >> >>>[/color]
                    >>[/color][/color]
                    I guess I'm 'broken' :)
                    --
                    Robin Becker

                    Comment

                    • Andrew Clover

                      #11
                      Re: Division oddity

                      Raymond Hettinger <python@rcn.com > wrote:
                      [color=blue]
                      > So, the way to get eval() to respond to the import is to pass along
                      > the current environment:[/color]
                      [color=blue][color=green][color=darkred]
                      > >>> from __future__ import division
                      > >>> eval('9/2', globals())[/color][/color]
                      > 4.5[/color]

                      You can also put a future-import in the string, allowing you to run code
                      with features not known until run-time (and without affecting the host
                      script). Of course the catch is that import is a statement, not an
                      expression, so you have to do it with 'exec', eg.:

                      expr= '9/2'
                      features= 'division'
                      scope= {}
                      exec 'from __future__ import %s\n__assign= (%s)'%(features ,expr) in scope
                      print scope['__assign']

                      4.5

                      What you then *can't* do is have a future-import in the host script without
                      it affecting the script in the exec block.

                      Python 2.2+ has a much nicer way of doing it involving passing flags to the
                      'compile' function, which is preferable if you don't need backwards
                      compatibility.

                      Anyway, straying from the original point here.

                      Comment

                      • Michael Hudson

                        #12
                        Re: Division oddity

                        Paul Rubin <http://phr.cx@NOSPAM.i nvalid> writes:
                        [color=blue]
                        > Peter Hansen <peter@engcorp. com> writes:[color=green][color=darkred]
                        > > > Python has no support for macros or aliases, and it would be silly
                        > > > to add some special kludge for input(). The user needs to be able
                        > > > to redefine the function and so forth too.[/color]
                        > >
                        > > Sure it does:
                        > >
                        > > def input(*args):
                        > > return eval(raw_input( *args))[/color]
                        >
                        > For it to be an alias, that definition would have to be injected into
                        > the module that input is actually called from, not run in a separate
                        > module.[/color]

                        The problem with doing things this way is that it's not easy to get
                        Python-defined functions into an extension module. Nothing deep.
                        [color=blue]
                        > How the heck does input get at the environment of its caller, anyway?
                        > Through the frame object chain?[/color]

                        Yes. The function you are seeking is called
                        PyEval_MergeCom pilerFlags.
                        [color=blue]
                        > I guess the obvious fix is for the future division flag to be part of
                        > the environment, so evaling in the caller environment is done according
                        > to the flag.[/color]

                        I'm not sure what you mean here. eval() already respects future
                        division, as does execfile() and compile(). input() just got
                        overlooked when this stuff got added (back in the 2.1 era for nested
                        scopes, though the details have changed intermittently over the
                        intervening vwersions).
                        [color=blue]
                        > Someone has already checked a fix into sourceforge, but I haven't
                        > looked at it and don't know if it works that way or some other way.[/color]

                        Wouldn't checking have taken about as much time as writing the above
                        post? It's a very simple patch...

                        Cheers,
                        mwh

                        --
                        All obscurity will buy you is time enough to contract venereal
                        diseases. -- Tim Peters, python-dev

                        Comment

                        • Michael Hudson

                          #13
                          Re: Division oddity

                          Peter Hansen <peter@engcorp. com> writes:
                          [color=blue]
                          > Michael Hudson wrote:[color=green]
                          > >
                          > > Peter Hansen <peter@engcorp. com> writes:
                          > >[color=darkred]
                          > > > Tim Rowe wrote:
                          > > > >
                          > > > > Well, the documentation for "input()" says "Equivalent to
                          > > > > eval(raw_input(/prompt/))". Perhaps it should say "/Usually/
                          > > > > equivalent...."
                          > > >
                          > > > I remember reading that too, and just assumed that at this point
                          > > > it was in fact *implemented* that way, as a simple alias. Maybe
                          > > > it should be...[/color]
                          > >
                          > > http://www.python.org/sf/876178
                          > >
                          > > Ideas on how to write a testcase welcome.[/color]
                          >
                          > Are there any test cases which verify behaviour both in the presence
                          > and absence of certain "from __future__ import" statements?[/color]

                          Yes.
                          [color=blue]
                          > My first thought would have been simply to write two test files,
                          > one of which imports from __future__ and the other which does not,
                          > and check that in both cases input(x) == eval(raw_input( x)).
                          >
                          > Or is the issue how to test when the input comes from stdin? In
                          > that case, doesn't faking sys.stdin work as usual?[/color]

                          Oh, probably...

                          Cheers,
                          mwh

                          --
                          I'll write on my monitor fifty times 'I must not post self-indulgent
                          wibble nobody is interested in to ucam.chat just because I'm bored
                          and I can't find the bug I'm supposed to fix'.
                          -- Steve Kitson, ucam.chat

                          Comment

                          Working...