test for nan

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Hunter

    test for nan


    I have a C extension module that is returning some doubles. When the
    doubles get out of range, the numbers print as 'nan'.

    Is there a better way to test for NaN than

    str(p1)=='nan'

    where p1 is a float?

    python2.3

    Thanks,
    John Hunter

  • David M. Cooke

    #2
    Re: test for nan

    At some point, John Hunter <jdhunter@ace.b sd.uchicago.edu > wrote:
    [color=blue]
    > I have a C extension module that is returning some doubles. When the
    > doubles get out of range, the numbers print as 'nan'.
    >
    > Is there a better way to test for NaN than
    >
    > str(p1)=='nan'
    >
    > where p1 is a float?[/color]

    The string representation of NaN is system-dependent. On Windows it's
    something like #NaN. You'd be better off with Jeff Epler's suggestion
    of wrapping isnan() (since you already have a C extension module, you
    could through it in there).

    If you're on something that uses IEEE floating-point representations ,
    something like this in pure python should work:

    import struct
    def isnan(x):
    s = struct.pack('d' , x)
    if struct.pack('h' , 1) == '\x01\x00':
    return s == '\x00\x00\x00\x 00\x00\x00\xf0\ x7f':
    else:
    return s == '\x7f\xf8\x00\x 00\x00\x00\x00\ x00':

    The test for endianness is there since struct.unpack(' <d', x)
    complains that frexp() is out of range.

    --
    |>|\/|<
    /--------------------------------------------------------------------------\
    |David M. Cooke
    |cookedm(at)phy sics(dot)mcmast er(dot)ca

    Comment

    • Michael Hudson

      #3
      Re: test for nan

      John Hunter <jdhunter@ace.b sd.uchicago.edu > writes:
      [color=blue]
      > I have a C extension module that is returning some doubles. When the
      > doubles get out of range, the numbers print as 'nan'.
      >
      > Is there a better way to test for NaN than
      >
      > str(p1)=='nan'
      >
      > where p1 is a float?[/color]

      I'd hope so: that's exceeding unportable. Of course, all things to do
      with nans are unportable, so you're going to have to tell us more of
      your requirements...

      Cheers,
      mwh

      --
      I have *both* hands clapping, but I'm still not sure it's a sound.
      When I tried deciding if it were a sound while clapping only one
      hand, I fell off my chair.
      -- Peter Hansen, Zen master, comp.lang.pytho n

      Comment

      • Peter Maas

        #4
        Re: test for nan

        John Hunter wrote:[color=blue]
        > I have a C extension module that is returning some doubles. When the
        > doubles get out of range, the numbers print as 'nan'.
        >
        > Is there a better way to test for NaN than
        >
        > str(p1)=='nan'
        >
        > where p1 is a float?
        >
        > python2.3
        >
        > Thanks,
        > John Hunter
        >[/color]

        As far as I know NaN is th only value that yields false when compared
        to itself. This leads to

        def isNaN(x):
        return (x == x) == False

        Mit freundlichen Gruessen,

        Peter Maas

        --
        -------------------------------------------------------------------
        Peter Maas, M+R Infosysteme, D-52070 Aachen, Hubert-Wienen-Str. 24
        Tel +49-241-93878-0 Fax +49-241-93878-20 eMail peter.maas@mplu sr.de
        -------------------------------------------------------------------

        Comment

        • Peter Maas

          #5
          Re: test for nan

          Peter Maas wrote:[color=blue]
          > John Hunter wrote:[color=green]
          >> Is there a better way to test for NaN than
          >>
          >> str(p1)=='nan'
          >>
          >> where p1 is a float?[/color]
          > [...]
          > As far as I know NaN is th only value that yields false when compared
          > to itself. This leads to
          >
          > def isNaN(x):
          > return (x == x) == False[/color]

          Shorter:

          def isNaN(x):
          return x != x

          Mit freundlichen Gruessen,

          Peter Maas

          --
          -------------------------------------------------------------------
          Peter Maas, M+R Infosysteme, D-52070 Aachen, Hubert-Wienen-Str. 24
          Tel +49-241-93878-0 Fax +49-241-93878-20 eMail peter.maas@mplu sr.de
          -------------------------------------------------------------------

          Comment

          • Peter Otten

            #6
            Re: test for nan

            Peter Maas wrote:
            [color=blue]
            > As far as I know NaN is th only value that yields false when compared
            > to itself. This leads to
            >
            > def isNaN(x):
            > return (x == x) == False[/color]

            That is not portable:

            Python 2.3.3 (#1, Jan 3 2004, 13:57:08)
            [GCC 3.2] on linux2
            Type "help", "copyright" , "credits" or "license" for more information.[color=blue][color=green][color=darkred]
            >>> nan = float("nan")
            >>> nan != nan[/color][/color][/color]
            False


            Peter

            Comment

            • Peter Maas

              #7
              Re: test for nan

              Peter Otten wrote:[color=blue][color=green]
              >>def isNaN(x):
              >> return (x == x) == False[/color]
              >
              >
              > That is not portable:
              >
              > Python 2.3.3 (#1, Jan 3 2004, 13:57:08)
              > [GCC 3.2] on linux2
              > Type "help", "copyright" , "credits" or "license" for more information.
              >[color=green][color=darkred]
              >>>>nan = float("nan")
              >>>>nan != nan[/color][/color]
              >
              > False[/color]

              Thanks for correction. I firmly believed that NaN != NaN -> True
              was a property of IEEE 754 and of all software using this standard.
              For gcc/Linux you could use

              def isNaN(x):
              return (x == 0) and (x == 1)

              and utilize sys.platform. :)

              Mit freundlichen Gruessen,

              Peter Maas

              --
              -------------------------------------------------------------------
              Peter Maas, M+R Infosysteme, D-52070 Aachen, Hubert-Wienen-Str. 24
              Tel +49-241-93878-0 Fax +49-241-93878-20 eMail peter.maas@mplu sr.de
              -------------------------------------------------------------------

              Comment

              • Michael Hudson

                #8
                Re: test for nan

                Peter Maas <fpetermaas@net scape.net> writes:
                [color=blue]
                > John Hunter wrote:[color=green]
                > > I have a C extension module that is returning some doubles. When the
                > > doubles get out of range, the numbers print as 'nan'.
                > > Is there a better way to test for NaN than
                > > str(p1)=='nan'
                > > where p1 is a float?
                > > python2.3
                > > Thanks,
                > > John Hunter
                > >[/color]
                >
                > As far as I know NaN is th only value that yields false when
                > compared to itself.[/color]

                There can be more than one NaN, by the way.
                [color=blue]
                > This leads to
                >
                > def isNaN(x):
                > return (x == x) == False[/color]

                This will work with 2.3 on Windows (I believe), current CVS on Windows
                (if compiled with VC7.1), current CVS on Linux (assuming an even
                vaguely recent gcc), but not current CVS on Windows compiled with VC6,
                nor Python 2.3 on Linux/gcc. Confused yet?

                Other platforms I haven't the faintest idea about.

                Cheers,
                mwh

                --
                41. Some programming languages manage to absorb change, but
                withstand progress.
                -- Alan Perlis, http://www.cs.yale.edu/homes/perlis-alan/quotes.html

                Comment

                • Peter Otten

                  #9
                  Re: test for nan

                  Peter Maas wrote:
                  [color=blue]
                  > def isNaN(x):
                  > return (x == 0) and (x == 1)[/color]

                  This works here. Do you have an idea what the rationale behind this
                  behaviour (i. e. any number == nan) is?

                  Peter

                  Comment

                  • John Hunter

                    #10
                    Re: test for nan

                    >>>>> "Michael" == Michael Hudson <mwh@python.net > writes:

                    Michael> This will work with 2.3 on Windows (I believe), current
                    Michael> CVS on Windows (if compiled with VC7.1), current CVS on
                    Michael> Linux (assuming an even vaguely recent gcc), but not
                    Michael> current CVS on Windows compiled with VC6, nor Python 2.3
                    Michael> on Linux/gcc. Confused yet?

                    Fortunately I only need linux for this particular app, so I can use
                    one of the platform dependent solutions, but the bevy of proposed
                    solutions and gotchas have definitely been interesting.

                    Out of curiosity, are there any platforms where this is known to fail?

                    def is_nan(x):
                    return str(x).lower(). find('nan')>=0

                    JDH

                    Comment

                    • Roel Schroeven

                      #11
                      Re: test for nan

                      John Hunter wrote:[color=blue]
                      > Out of curiosity, are there any platforms where this is known to fail?
                      >
                      > def is_nan(x):
                      > return str(x).lower(). find('nan')>=0[/color]

                      Yes...

                      Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)] on
                      win32

                      IDLE 1.0.2[color=blue][color=green][color=darkred]
                      >>> def is_nan(x):[/color][/color][/color]
                      return str(x).lower(). find('nan') >= 0
                      [color=blue][color=green][color=darkred]
                      >>> inf=float('1e99 99')
                      >>> inf[/color][/color][/color]
                      1.#INF[color=blue][color=green][color=darkred]
                      >>> nan=inf-inf
                      >>> is_nan(nan)[/color][/color][/color]
                      False[color=blue][color=green][color=darkred]
                      >>> nan[/color][/color][/color]
                      -1.#IND

                      --
                      "Codito ergo sum"
                      Roel Schroeven

                      Comment

                      • Peter Maas

                        #12
                        Re: test for nan

                        Michael Hudson wrote:[color=blue]
                        > There can be more than one NaN, by the way.[/color]

                        I know that but if all NaNs have the same distinct algorithmic behaviour
                        that's not a problem.
                        [color=blue][color=green]
                        >>This leads to
                        >>
                        >>def isNaN(x):
                        >> return (x == x) == False[/color]
                        >
                        >
                        > This will work with 2.3 on Windows (I believe), current CVS on Windows
                        > (if compiled with VC7.1), current CVS on Linux (assuming an even
                        > vaguely recent gcc), but not current CVS on Windows compiled with VC6,
                        > nor Python 2.3 on Linux/gcc. Confused yet?[/color]

                        No:

                        def isNaN1(x):
                        return x != x

                        def isNaN2(x):
                        return (x == 0) and (x == 1)

                        if sys.platform == 'win32' and '2.3' in sys.version:
                        isNaN = isNaN1
                        elif sys.platform == 'win32' and 'good_CVS_VC_st uff' in sys.version:
                        isNaN = isNaN1
                        elif sys.platform == 'win32' and 'bad_CVS_VC_stu ff' in sys.version:
                        isNaN = isNaN2
                        elif sys.platform == 'linux2':
                        isNaN = isNaN2
                        else:
                        raise Exception, "Roll your own isNaN() for platform " \
                        "%s and version %s\n" % (sys.platform, sys.version)

                        bad/good_CVS_VC_stu ff has to be worked out, don't have the version strings
                        available.

                        Mit freundlichen Gruessen,

                        Peter Maas

                        --
                        -------------------------------------------------------------------
                        Peter Maas, M+R Infosysteme, D-52070 Aachen, Hubert-Wienen-Str. 24
                        Tel +49-241-93878-0 Fax +49-241-93878-20 eMail peter.maas@mplu sr.de
                        -------------------------------------------------------------------

                        Comment

                        Working...