From: "Michael W. Ryder" <_mwryder@...> Date: 2008-05-20T12:45:03+09:00 Subject: Re: Why doesn't Float() work the same as Integer()? Eric I. wrote: > On May 19, 7:44 pm, "Michael W. Ryder" <_mwry...@worldnet.att.net> > wrote: >> My question is why doesn't Float know how to deal with prefixes such as >> Hex? I wouldn't care if it tossed out invalid hex numbers such as 0x1h >> but it should at least try. As far as I am concerned the only >> difference between Float and Integer should be the return type, not what >> types they can handle. > > Well you're asking "why", and I suppose you'd have to address the > question to the core Ruby team. However, I can venture a guess, for > whatever that might be worth. And there are three elements to my > guess. > > First, Float() and Integer() work like Ruby itself. In Ruby code you > can hardcode integer literals using 17 (dec), 021 (oct), or 0x11 > (hex). But you can only hardcode floating point literals using base > ten. Admittedly, that's a bit of a punt since you'll probably ask why > Ruby works that way. > > Second, I've never had the need to represent a floating point value as > a hexadecimal literal or string. With integers you sometimes need bit > masks and such. Perhaps there are domains where this would be very > useful. But I imagine most programmers don't typically run into > them. And like anything, people are more likely to do things that > they believe will be useful, or they scratch their own itches. > I think my main concern was this was yet another "gotcha" that only came up if you tested for it. My original conversion for strings to floats was a simple: x = Float(x) if (Float(x) rescue false). This works fine for "12", and "12.34" but crashes if I use "0x11" or any other hex value, something Integer does not. What I ended up having to do is: temp = nil temp = Float(x) if (Float(x) rescue false) if temp == nil temp = Integer(x) if (Integer(x) rescue false) end if temp == nil x = 0 else x = temp end As you can see this is much more code, and that is before I add in more code for error handling. > And my third reason is that there might be ambiguity in how to > interpret such a string. The representation of floating point values > as a bit pattern is typically done using IEEE 754. So, if we wanted > to represent a PI as a floating point double as a hexadecimal > constant, I think it would be "0x400921fb54442d18". However that > could also be interpreted as the integer 4,614,256,656,552,045,848. > > Given your original post, you seem to be thinking that hexadecimal > constants would include a "." to separate the whole part from the > fractional part. In that case, I imagine pi would be represented as > "0x3.243f6a8885a3". > Actually I wouldn't care if it couldn't handle floating point numbers in any base except 10 as it doesn't appear to be able to do so in other methods like sprintf or printf. I don't think it would have been that hard to allow Float to handle strings like '0x11' as the code has already been created for Integer. > But for those programmers out there who'd want some type of > functionality, they may not be unified in their preference for the > format -- IEEE 754 or with an included decimal point. > > I don't know how satisfying you'll find those answers, but they're the > best I can do. > I have no problem with your replies and can see that maybe the original implementation was made to work correctly for a small subset of possible values rather than try to handle everything with possible problems. As I mentioned earlier I was trying to take the section on duck typing seriously and make my class handle as many reasonable inputs as possible. I will probably try to include arrays and strings like "17 4" as inputs once I finish the inputs for Integers, Floats, Rationals, and Strings in any combination. I hadn't thought about adding the ability to display Rational numbers in other bases but that should be trivial, at least compared to Floating point numbers. I would use something like 0x11/0x4 to represent 17/4. Since the numerator and denominator of my Rational numbers are always Integers converting should be easy. > By the way, if you want to include such functionality in your Rational > project, the following Ruby snippets might be helpful. > > To figure out how pi would be represented as an IEEE 754 encoded > value, I used the following Ruby code: > > "0x" + [Math::PI].pack("G").unpack("H*").first > > If you're unfamiliar with the methods, you may be interested in > reading the documentation on Array#pack and String#unpack. > > To figure out how pi would be represented in the other form, I used > this Ruby code: > > fractional_hex_digits = 12 # how many hex digits right of decimal > "0x" + > Math::PI.floor.to_s(16) + > "." + > ((Math::PI - Math::PI.floor) * > 16**fractional_hex_digits).floor.to_s(16) > > If you plan on using any of this code, please check my work since it > comes with absolutely to warranties. > > Best, > > Eric > > ==== > > LearnRuby.com offers Rails & Ruby HANDS-ON public & ON-SITE > workshops. > Ruby Fundamentals Wkshp June 16-18 Ann Arbor, Mich. > Ready for Rails Ruby Wkshp June 23-24 Ann Arbor, Mich. > Ruby on Rails Wkshp June 25-27 Ann Arbor, Mich. > Ruby Plus Rails Combo Wkshp June 23-27 Ann Arbor, Mich > Please visit http://LearnRuby.com for all the details.