"nan".to_f?

I ran into this difference:

···

---
irb(main):001:0> VERSION
"1.6.7"
irb(main):002:0> "nan".to_f
NaN
---
irb(main):001:0> VERSION
=> "1.8.2"
irb(main):002:0> "nan".to_f
=> 0.0
---

(1.8.2 is really 1.8.1+1.8.2pre2-1woody1 in Debian)

I wouldn't have been surprised if it was the other way round. Can
anyone explain why it is so? Seemed like a nice feature to me.

--
Thomas
beast@system-tnt.dk

Thomas Fini Hansen wrote:

I ran into this difference:

---
irb(main):001:0> VERSION
"1.6.7"
irb(main):002:0> "nan".to_f
NaN
---
irb(main):001:0> VERSION
=> "1.8.2"
irb(main):002:0> "nan".to_f
=> 0.0
---

(1.8.2 is really 1.8.1+1.8.2pre2-1woody1 in Debian)

I wouldn't have been surprised if it was the other way round. Can
anyone explain why it is so? Seemed like a nice feature to me.

Why would Ruby turn "nan" to "NaN" when you told it to convert the string to a float? I don't see the connection.

Robo

Hi Thomas, hi Rubyists

Thomas Fini Hansen wrote:

---
irb(main):001:0> VERSION
"1.6.7"
irb(main):002:0> "nan".to_f
NaN
---
irb(main):001:0> VERSION
=> "1.8.2"
irb(main):002:0> "nan".to_f
=> 0.0
---

(1.8.2 is really 1.8.1+1.8.2pre2-1woody1 in Debian)

I wouldn't have been surprised if it was the other way round. Can
anyone explain why it is so? Seemed like a nice feature to me.

>ri String#to_f
------------------------------------------------------------ String#to_f
      str.to_f => float

···

------------------------------------------------------------------------
      Returns the result of interpreting leading characters in _str_ as a
      floating point number. Extraneous characters past the end of a
      valid number are ignored. If there is not a valid number at the
      start of _str_, +0.0+ is returned. This method never raises an
      exception.

         "123.45e1".to_f #=> 1234.5

         "45.67 degrees".to_f #=> 45.67

         "thx1138".to_f #=> 0.0

I don't use String#to_f a lot, because I'd prefer Float( a_string ).
Float() is stricter and raises an ArgumentError if the whole String can't be interpreted as a Float, while String#to_s tries to create a Float from the first characters and stops when/if there are any chars that wouldn't yield a Float.

Happy rubying

Stephan

Robo ha scritto:

Why would Ruby turn "nan" to "NaN" when you told it to convert the string to a float? I don't see the connection.

NaN stands for Not a Number and is a 'builtin' value in floating point math system (I mean, at the cpu level)

Yes, but his point is that "NaN" _is_ the string representation of
valid floating point value, defined and handled by the system, with
standardized semantics, etc.
    "NaN".to_f should return NaN. How else are you going to reliably
get NaN if you need it?
    IMO, this is a bug.

     -- Markus

···

On Tue, 2004-10-12 at 02:39, Stephan Kämper wrote:

Hi Thomas, hi Rubyists

Thomas Fini Hansen wrote:

> ---
> irb(main):001:0> VERSION
> "1.6.7"
> irb(main):002:0> "nan".to_f
> NaN
> ---
> irb(main):001:0> VERSION
> => "1.8.2"
> irb(main):002:0> "nan".to_f
> => 0.0
> ---
>
> (1.8.2 is really 1.8.1+1.8.2pre2-1woody1 in Debian)
>
> I wouldn't have been surprised if it was the other way round. Can
> anyone explain why it is so? Seemed like a nice feature to me.
>

>ri String#to_f
------------------------------------------------------------ String#to_f
      str.to_f => float
------------------------------------------------------------------------
      Returns the result of interpreting leading characters in _str_ as a
      floating point number. Extraneous characters past the end of a
      valid number are ignored. If there is not a valid number at the
      start of _str_, +0.0+ is returned. This method never raises an
      exception.

         "123.45e1".to_f #=> 1234.5

         "45.67 degrees".to_f #=> 45.67

         "thx1138".to_f #=> 0.0

I don't use String#to_f a lot, because I'd prefer Float( a_string ).
Float() is stricter and raises an ArgumentError if the whole String
can't be interpreted as a Float, while String#to_s tries to create a
Float from the first characters and stops when/if there are any chars
that wouldn't yield a Float.

Happy rubying

Stephan

Markus <markus@reality.com> writes:

     Yes, but his point is that "NaN" _is_ the string representation of
valid floating point value, defined and handled by the system, with
standardized semantics, etc.
    "NaN".to_f should return NaN. How else are you going to reliably
get NaN if you need it?

0.0/0.0? :slight_smile:

Mikael Brockman wrote:

    Yes, but his point is that "NaN" _is_ the string representation of
valid floating point value, defined and handled by the system, with
standardized semantics, etc. "NaN".to_f should return NaN. How else are you going to reliably
get NaN if you need it?

When would you *need* NaN in the first place? To show the the result of some calculation is NaN? The just return that calculation.

To test whether something is NaN? -> There's Float#nan? to do that.

0.0/0.0? :slight_smile:

Happy rubying

Stephan

I almost went off on an IEEE spiel until I saw the ":-)"

     -- Markus

···

On Tue, 2004-10-12 at 09:22, Mikael Brockman wrote:

Markus <markus@reality.com> writes:

> Yes, but his point is that "NaN" _is_ the string representation of
> valid floating point value, defined and handled by the system, with
> standardized semantics, etc.
> "NaN".to_f should return NaN. How else are you going to reliably
> get NaN if you need it?

0.0/0.0? :slight_smile:

Markus <markus@reality.com> writes:

···

On Tue, 2004-10-12 at 09:22, Mikael Brockman wrote:
> Markus <markus@reality.com> writes:
>
> > Yes, but his point is that "NaN" _is_ the string representation of
> > valid floating point value, defined and handled by the system, with
> > standardized semantics, etc.
> > "NaN".to_f should return NaN. How else are you going to reliably
> > get NaN if you need it?
>
> 0.0/0.0? :slight_smile:

     I almost went off on an IEEE spiel until I saw the ":-)"

Actually, I'm as ignorant as you first assumed. Feel free to spiel if
you want. :slight_smile:

When would you *need* NaN in the first place? To show the the result of
some calculation is NaN? The just return that calculation.

     I don't have a specific example in mind. Perhaps you're writing
something that evaluates a parameterized infinite series and want to
return NaN in the case where it doesn't converge (this being
significantly faster than an infinite loop). Who knows?

     There may be other, better examples, but the point is _someone_ has
to be able to generate NaN, at some level (else we'd never see it) and
so it is at least plausible that that someone might be one of us.

To test whether something is NaN? -> There's Float#nan? to do that.

     Good point.

-- Markus

Mikael Brockman wrote:
>> Yes, but his point is that "NaN" _is_ the string representation of
>>valid floating point value, defined and handled by the system, with
>>standardized semantics, etc.
>> "NaN".to_f should return NaN. How else are you going to reliably
>>get NaN if you need it?

When would you *need* NaN in the first place? To show the the result of
some calculation is NaN? The just return that calculation.

Well, my case was pretty simple, I'm parsing the output of RRDTool,
which uses floats internally, and writes 'nan' for unknown data.

To test whether something is NaN? -> There's Float#nan? to do that.

Well, that was what I wanted to do, later, but now I have to check for
the string 'nan' at parse time, or else I'll get 0.0, when it's not
quite.

I would say that 'NaN' is a the string representation of a float, so
logically it should be parsed to such, that's why I'm wondering why
this behaviour was *removed*.

Not that it's an unsurmountable problem for what I'm doing, it's just
nicer and cleaner.

···

On Wed, Oct 13, 2004 at 01:49:37AM +0900, Stephan Kämper wrote:

--
Thomas
beast@system-tnt.dk

Short form: there are several NaN's, and "NaN like values" (e.g. +/-
infinity) and IIRC the form you gave could arguably return almost any of
them (except maybe -0.0).

-- Markus

http://www.freesoft.org/CIE/RFC/1832/32.htm

···

On Tue, 2004-10-12 at 10:15, Mikael Brockman wrote:

Markus <markus@reality.com> writes:

> On Tue, 2004-10-12 at 09:22, Mikael Brockman wrote:
> > Markus <markus@reality.com> writes:
> >
> > > Yes, but his point is that "NaN" _is_ the string representation of
> > > valid floating point value, defined and handled by the system, with
> > > standardized semantics, etc.
> > > "NaN".to_f should return NaN. How else are you going to reliably
> > > get NaN if you need it?
> >
> > 0.0/0.0? :slight_smile:
>
> I almost went off on an IEEE spiel until I saw the ":-)"

Actually, I'm as ignorant as you first assumed. Feel free to spiel if
you want. :slight_smile:

Hi,

I would say that 'NaN' is a the string representation of a float, so
logically it should be parsed to such, that's why I'm wondering why
this behaviour was *removed*.

It's not valid string representation of a float.

ruby -e 'nan'
-e:1: undefined local variable or method `nan' for main:Object (NameError)

ruby -e 'NaN'
-e:1: uninitialized constant NaN (NameError)

Ruby used to use system's strtod(3), which gives you "nan" an "inf"
for free, but its interpretation varies a little from platform to
platform. Now it uses its own version of strtod that interprets only
valid float representation in Ruby.

              matz.

···

In message "Re: "nan".to_f ?" on Wed, 13 Oct 2004 05:22:00 +0900, Thomas Fini Hansen <beast@system-tnt.dk> writes:

>I would say that 'NaN' is a the string representation of a float, so
>logically it should be parsed to such, that's why I'm wondering why
>this behaviour was *removed*.

It's not valid string representation of a float.

      Then why does:

x = 0.0/0.0
x.class #Float
x.to_s #NaN

      If "NaN" is not the valid string representation of a Float, why
does calling Float#to_s return it?

Ruby used to use system's strtod(3), which gives you "nan" an
"inf" for free, but its interpretation varies a little from platform
to platform. Now it uses its own version of strtod that interprets
only valid float representation in Ruby.

     The problem with this (in addition to some of my other contrived
examples, e.g. the non-convergent infinite series) is that we may want
to convert values to text and back (e.g., making XML) and would like to
be able to get something resembling the original values back.
     Admittedly, it would be possible for users who wanted this to do it
themselves, but the performance consequences could be considerable.

     -- Markus

Hi,

···

In message "Re: "nan".to_f ?" on Wed, 13 Oct 2004 21:18:38 +0900, Markus <markus@reality.com> writes:

It's not valid string representation of a float.

     Then why does:

x = 0.0/0.0
x.class #Float
x.to_s #NaN

     If "NaN" is not the valid string representation of a Float, why
does calling Float#to_s return it?

Although we can tell whether a float value is NaN by using isnan(),
but as far as I know there's no portably way to generate NaN. I think
it's not guaranteed that 0.0/0.0 generate NaN.

If I'm wrong, feel free to correct me.

              matz.

Hi,

Markus wrote:

     The problem with this (in addition to some of my other contrived
examples, e.g. the non-convergent infinite series) is that we may want
to convert values to text and back (e.g., making XML) and would like to
be able to get something resembling the original values back.
     Admittedly, it would be possible for users who wanted this to do it
themselves, but the performance consequences could be considerable.

     -- Markus

I think there's not even a problem (or an SEP). You could easily

- Add NaN as a constant to class Float
- Implement String#to_f slightly bot not entirely different
   so as to return NaN if the string begins with NaN

Something like this:

class Float
   NaN = 0.0 / 0.0
end

class String
   alias old_to_f to_f

   def to_f
     ( self =~ /^nan/i ) ? Float::NaN : self.old_to_f
   end
end

strings = [ "NaN1234", "nan", "nand is locical", "Nantucket? 70°07'W 41°18'N", "234234.234NaN", "1.0e23" ]

strings.each { | s |
   puts "#{'%26s' % s} -> #{ s.to_f }"
}

Apparently this processing doesn't make sense for all Strings...

Happy rubying

Stephan

Yukihiro Matsumoto <matz@ruby-lang.org> wrote in message news:<1097623876.470219.23507.nullmailer@x31.priv.netlab.jp>...

Hi,

>I would say that 'NaN' is a the string representation of a float, so
>logically it should be parsed to such, that's why I'm wondering why
>this behaviour was *removed*.

It's not valid string representation of a float.

[...]

Maybe I'm too late to jump in to this old thread
(three-days old is old enough for people to forget about
a thread :). Anyway, . . .

I think that symmetry is important, or if not important, it's nice
to have. So, *if*

   x = 0.0/0.0 #=> NaN
   x.to_s #=> "NaN"

*then*

   y = "NaN".to_f # y *should* be NaN.

In other words, I'd expect (x.to_s).to_f to be an identity
operation (apart from potential truncation associated with to_s)
for a Float x.

I'm not saying that 0.0/0.0 *should* evaluate to NaN. That depends
on the platform. What I'm saying is that whatever x.to_s evaluates
to, (x.to_s).to_f "should" recover the (more-or-less) original value.
By "should", I mean "I wish".

Same goes for "Inf" and "-Inf".

Cheers,
Ryo

···

In message "Re: "nan".to_f ?" > on Wed, 13 Oct 2004 05:22:00 +0900, Thomas Fini Hansen <beast@system-tnt.dk> writes:

Not sure if portable, but one might try

  (-1.0) ** 0.5

(Interesting also that '**' precedence is greater than '-'.)

T.

···

On Wednesday 13 October 2004 08:38 am, Yukihiro Matsumoto wrote:

Hi,

In message "Re: "nan".to_f ?" > > on Wed, 13 Oct 2004 21:18:38 +0900, Markus <markus@reality.com> writes:
>> It's not valid string representation of a float.
>
> Then why does:
>
>x = 0.0/0.0
>x.class #Float
>x.to_s #NaN
>
> If "NaN" is not the valid string representation of a Float, why
>does calling Float#to_s return it?

Although we can tell whether a float value is NaN by using isnan(),
but as far as I know there's no portably way to generate NaN. I think
it's not guaranteed that 0.0/0.0 generate NaN.

In message Re: "nan".to_f ?

Although we can tell whether a float value is NaN by using isnan(),
but as far as I know there's no portably way to generate NaN. I think
it's not guaranteed that 0.0/0.0 generate NaN.

  def aNaN
    s, e, m = rand(2), 2047, rand(2**52-1)+1
    [sprintf("%1b%011b%052b", s,e,m)].pack("B*").unpack("G").first
  end

I believe this will generate NaN on environments where
pack/unpack works and NaN exists.

Gotoken

···

on Wed, 13 Oct 2004 21:38:22 +0900, Yukihiro Matsumoto wrote:

No, so far as I know you are correct (at as far as math operations
go). There was another sub-thread on this topic regarding the
assumption that 0.0/0.0 could be PosInf, NegInf, Inf, or NaN.

     I believe there are defined binary representation of IEEE NaNs, so
one could be constructed. (See, for example

http://www.psc.edu/general/software/packages/ieee/ieee.html

), which I suspect is how the libs do it.

     If we could count on 0.0/0.0 to always produce NaN, I believe the
original poster's goal could be met by writing something like:

        class String
            def to_i
                 Integer(self) rescue 0.0/0.0
                 end
            end
        
...although this may not be as general as he needed.

-- Markus

···

On Wed, 2004-10-13 at 05:38, Yukihiro Matsumoto wrote:

Hi,

In message "Re: "nan".to_f ?" > on Wed, 13 Oct 2004 21:18:38 +0900, Markus <markus@reality.com> writes:

>> It's not valid string representation of a float.
>
> Then why does:
>
>x = 0.0/0.0
>x.class #Float
>x.to_s #NaN
>
> If "NaN" is not the valid string representation of a Float, why
>does calling Float#to_s return it?

Although we can tell whether a float value is NaN by using isnan(),
but as far as I know there's no portably way to generate NaN. I think
it's not guaranteed that 0.0/0.0 generate NaN.

If I'm wrong, feel free to correct me.