"nan".to_f ?

T

Thomas Fini Hansen

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.
 
R

Robo

Thomas said:
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
 
G

gabriele renzi

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)
 
S

Stephan Kämper

Hi Thomas, hi Rubyists
---
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
 
M

Markus

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
 
M

Mikael Brockman

Markus said:
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? :)
 
M

Mikael Brockman

Markus said:
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. :)
 
M

Markus

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
 
T

Thomas Fini Hansen

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.
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: "nan".to_f ?"

|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.
 
M

Markus

|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
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: "nan".to_f ?"

|> 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.
 
S

Stephan Kämper

Hi,
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
 
T

trans. (T. Onoma)

On Wednesday 13 October 2004 08:38 am, Yukihiro Matsumoto wrote:
| Hi,
|
| In message "Re: "nan".to_f ?"
|
| |> 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.

Not sure if portable, but one might try

(-1.0) ** 0.5

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

T.
 
G

GOTO Kentaro

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
 
M

Markus

Hi,

In message "Re: "nan".to_f ?"

|> 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.

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
 
M

Markus

That should have been:
class String
def to_f
Float(self) rescue 0.0/0.0
end
end

...I really shouldn't post before caffeination, esp. after being up half
the night chasing my son's imaginary tigers out of the house.

-- Markus
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: "nan".to_f ?"

| 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.

If the platform uses IEEE floating number, right?

matz.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,241
Latest member
Lisa1997

Latest Threads

Top