Strange result with math.atan2()

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Vedran Furač

    #1

    Strange result with math.atan2()

    I think that this results must be the same:

    In [3]: math.atan2(-0.0,-1)
    Out[3]: -3.1415926535897 931

    In [4]: math.atan2(-0,-1)
    Out[4]: 3.1415926535897 931

    In [5]: -0 == -0.0
    Out[5]: True


    This is python 2.4.4c0 on Debian GNU/Linux.


    Regards,

    Vedran Furač


  • Peter Otten

    #2
    Re: Strange result with math.atan2()

    Vedran Fura? wrote:
    [color=blue]
    > I think that this results must be the same:
    >
    > In [3]: math.atan2(-0.0,-1)
    > Out[3]: -3.1415926535897 931
    >
    > In [4]: math.atan2(-0,-1)
    > Out[4]: 3.1415926535897 931
    >
    > In [5]: -0 == -0.0
    > Out[5]: True[/color]

    Glimpsing at the hardware formats:
    [color=blue][color=green][color=darkred]
    >>> struct.pack("d" , 0.0)[/color][/color][/color]
    '\x00\x00\x00\x 00\x00\x00\x00\ x00'[color=blue][color=green][color=darkred]
    >>> struct.pack("d" , -0.0)[/color][/color][/color]
    '\x00\x00\x00\x 00\x00\x00\x00\ x80'[color=blue][color=green][color=darkred]
    >>> struct.pack("i" , -0)[/color][/color][/color]
    '\x00\x00\x00\x 00'[color=blue][color=green][color=darkred]
    >>> struct.pack("i" , 0)[/color][/color][/color]
    '\x00\x00\x00\x 00'

    -0 and +0 integers are identical while 0.0 and -0.0 floats are not. The
    negative sign is therefore lost before the int --> float conversion takes
    place.

    Peter

    Comment

    • Ben Caradoc-Davies

      #3
      Re: Strange result with math.atan2()

      Vedran Furač wrote:[color=blue]
      > I think that this results must be the same:
      > In [3]: math.atan2(-0.0,-1)
      > Out[3]: -3.1415926535897 931
      > In [4]: math.atan2(-0,-1)
      > Out[4]: 3.1415926535897 931[/color]

      -0 is converted to 0, then to 0.0 for calculation, losing the sign. You
      might as well write 0.0 instead of -0

      The behaviour of atan2 conforms to the ISO C99 standard (Python is
      implemented in C). Changing the sign of the first argument changes the
      sign of the output, with no special treatment for zero.
      [color=blue]
      > In [5]: -0 == -0.0
      > Out[5]: True[/color]

      The constant -0 is an integer and is immediately converted to 0 (an
      integer). Two's-complement integers have no separate sign bit, and only
      one representation for zero. The integer -0 is identical in all respects
      to the integer 0

      The constant -0.0 is a float, stored as an IEEE 754 bit pattern, and has
      a bit used to represent sign. The constants 0.0 and -0.0 compare equal,
      and both compare equal to 0, yet 0.0 and -0.0 have distinct bit patterns.

      Because Python uses the C implementation of atan2, both arguments are
      converted to floats before calculation. -0 is converted to 0, then to 0.0

      The behaviour of atan2 is mandated by ISO C99 (ISO/IEC 9899:1999). See
      the manuals of some implementers who tabulate these special values:




      --
      Ben Caradoc-Davies <ben@wintersun. org>
      A milestone document in the history of human rights, the Universal Declaration of Human Rights set out, for the first time, fundamental human rights to be universally protected. It has been translated into over 500 languages.

      "Those who deny freedom to others deserve it not for themselves."
      - Abraham Lincoln

      Comment

      • Vedran Furač

        #4
        Re: Strange result with math.atan2()

        Ben Caradoc-Davies wrote:[color=blue]
        > Vedran Furač wrote:[color=green]
        >> I think that this results must be the same:
        >> In [3]: math.atan2(-0.0,-1)
        >> Out[3]: -3.1415926535897 931
        >> In [4]: math.atan2(-0,-1)
        >> Out[4]: 3.1415926535897 931[/color]
        >
        > -0 is converted to 0, then to 0.0 for calculation, losing the sign. You
        > might as well write 0.0 instead of -0
        >
        > The behaviour of atan2 conforms to the ISO C99 standard (Python is
        > implemented in C). Changing the sign of the first argument changes the
        > sign of the output, with no special treatment for zero.
        >
        > http://www.ugcs.caltech.edu/manuals/...0/mpfr_22.html[/color]

        Well, here I can read:

        Special values are currently handled as described in the ISO C99 standard
        for the atan2 function (note this may change in future versions):

        * atan2(+0, -0) returns +Pi.
        * atan2(-0, -0) returns -Pi. /* wrong too */
        * atan2(+0, +0) returns +0.
        * atan2(-0, +0) returns -0. /* wrong too */
        * atan2(+0, x) returns +Pi for x < 0.
        * atan2(-0, x) returns -Pi for x < 0
        ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^

        And the formula (also from that site):
        if x < 0, atan2(y, x) = sign(y)*(PI - atan (abs(y/x)))
        ^^^^^^^

        So, you can convert -0 to 0, but you must multiply the result with sign of
        y, which is '-' (minus).

        Also, octave:

        octave2.9:1> atan2(-0,-1)
        ans = -3.1416

        or matlab:
        [color=blue][color=green]
        >> atan2(-0,-5)[/color][/color]

        ans =

        -3.1416

        Comment

        • Serge Orlov

          #5
          Re: Strange result with math.atan2()

          Vedran Furac wrote:[color=blue]
          > Ben Caradoc-Davies wrote:[color=green]
          > > Vedran Furac wrote:[color=darkred]
          > >> I think that this results must be the same:
          > >> In [3]: math.atan2(-0.0,-1)
          > >> Out[3]: -3.1415926535897 931
          > >> In [4]: math.atan2(-0,-1)
          > >> Out[4]: 3.1415926535897 931[/color]
          > >
          > > -0 is converted to 0, then to 0.0 for calculation, losing the sign. You
          > > might as well write 0.0 instead of -0
          > >
          > > The behaviour of atan2 conforms to the ISO C99 standard (Python is
          > > implemented in C). Changing the sign of the first argument changes the
          > > sign of the output, with no special treatment for zero.
          > >
          > > http://www.ugcs.caltech.edu/manuals/...0/mpfr_22.html[/color]
          >
          > Well, here I can read:
          >
          > Special values are currently handled as described in the ISO C99 standard
          > for the atan2 function (note this may change in future versions):
          >
          > * atan2(+0, -0) returns +Pi.
          > * atan2(-0, -0) returns -Pi. /* wrong too */
          > * atan2(+0, +0) returns +0.
          > * atan2(-0, +0) returns -0. /* wrong too */
          > * atan2(+0, x) returns +Pi for x < 0.
          > * atan2(-0, x) returns -Pi for x < 0
          > ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
          >
          > And the formula (also from that site):
          > if x < 0, atan2(y, x) = sign(y)*(PI - atan (abs(y/x)))
          > ^^^^^^^
          >
          > So, you can convert -0 to 0, but you must multiply the result with sign of
          > y, which is '-' (minus).[/color]

          But you miss the fact that 0 is an *integer*, not a float, and -0
          doesn't exist.
          Use this code until you stop passing integers to atan2:

          from math import atan2 as math_atan2
          def atan2(y, x):
          if (isinstance(y, int) and y == 0) or (
          isinstance(x, int) and x == 0):
          raise ValueError("Arg ument that is an integer zero can \
          produce wrong results")
          return math_atan2(y, x)

          print atan2(-0.0, -0.0)
          print atan2(-0, -0)

          Comment

          • Vedran Furač

            #6
            Re: Strange result with math.atan2()

            Serge Orlov wrote:
            [color=blue][color=green]
            >> So, you can convert -0 to 0, but you must multiply the result with sign of
            >> y, which is '-' (minus).[/color]
            >
            > But you miss the fact that 0 is an *integer*, not a float, and -0
            > doesn't exist.[/color]

            Yes, you are right, I completely missed that 0 is integer in python, and I
            need a float.


            Regards,

            Vedran Furač

            Comment

            Working...