Code Critique: check if int or float

Hello again folks,

I’m really starting to like this language. I’m working towards building
a simple expression evaluator. I couldn’t seem to find any methods for
testing whether a string contains an integer or float. In PHP (where I’m
from) you’ve got your is_numeric(). Is there such a method in Ruby?

Anyway, under the assumption that there wasn’t and to learn a bit I
decided to add the methods i? and f? to String. I was wondering if I
could get a bit of a critique on this code because I’m still ultra new
to Ruby.

I’m a TDD maniac, so I’ve got miself a test case in there too:

class String

Strict test whether the string is a valid integer

Underscores are not permitted.

allowScientific is false by default because “4e3”.to_i is 4

def i?(allowScientific = false)
if allowScientific
return (self =~ /^-?\d+(e-?\d+)?$/) != nil
end
(self =~ /^-?\d+$/) != nil
end

Strict test whether the string is a valid float.

i.e. 4 is not but 4.0 is. Scientific notation acceptable.

def f?(allowScientific = true)
if allowScientific
return (self =~ /^-?\d*.\d+(e-?\d+)?$/) != nil
end
(self =~ /^-?\d*.\d+$/) != nil
end
end

require ‘test/unit’

class StringExtensionsTest < Test::Unit::TestCase
def testI
assert ‘45’.i?
assert ‘-3’.i?
assert !‘3s’.i?
assert !‘3_000’.i?
assert !‘3e3’.i?
end
def testIScientific
assert !‘e4’.i?(true)
assert ‘4e2’.i?(true)
assert ‘-8e3’.i?(true)
assert ‘-5e-25’.i?(true)
end
def testFBasic
assert !‘3’.f?(false)
assert ‘3.0’.f?(false)
assert ‘-25.36’.f?(false)
assert ‘.52’.f?(false)
assert ‘-.14’.f?(false)
end
def testFScientific
assert !‘e1’.f?
assert !‘4e1’.f?
assert ‘3.12e1’.f?
assert ‘-2.0e-3’.f?
assert ‘-.6e2’.f?
end
end

4 tests, 19 assertions, 0 failures, 0 errors

Final question, what are your feelings on camelCase and Ruby’s apparent
shunning of it?

On Thu, Jun 21, 2007 at 07:17:53AM +0900, ole __ wrote:

I’m really starting to like this language. I’m working towards building
a simple expression evaluator. I couldn’t seem to find any methods for
testing whether a string contains an integer or float. In PHP (where I’m
from) you’ve got your is_numeric(). Is there such a method in Ruby?

Anyway, under the assumption that there wasn’t and to learn a bit I
decided to add the methods i? and f? to String. I was wondering if I
could get a bit of a critique on this code because I’m still ultra new
to Ruby.

‘3s’.to_i
=> 3

Integer(‘3s’)
ArgumentError: invalid value for Integer: “3s”
from (irb):3:in `Integer’
from (irb):3

‘3s’.to_f
=> 3.0

Float(‘3s’)
ArgumentError: invalid value for Float(): “3s”
from (irb):5:in `Float’
from (irb):5

‘-8e3’.to_f
=> -8000.0

Float(’-8e3’)
=> -8000.0

‘-8e3’.to_i
=> -8

Integer(’-8e3’)
ArgumentError: invalid value for Integer: “-8e3”
from (irb):9:in `Integer’
from (irb):9

You could likely come up with a much cleaner implementation using
Integer() and Float() + rescue ArgumentError.

And about camelCase, it’s true, almost no one in Ruby uses
camelCase. I’d recommend just going with the flow and adoption
lowercase_and_underscored.

marcel

ole __ wrote:

Hello again folks,

I’m really starting to like this language. I’m working towards building
a simple expression evaluator. I couldn’t seem to find any methods for
testing whether a string contains an integer or float. In PHP (where I’m
from) you’ve got your is_numeric(). Is there such a method in Ruby?

The Integer() method raises an exception if its argument isn’t an
integer:

Integer(“1”) is okay.
Integer(“1.0”) raises ArgumentError.

Similarly Float() raises an exception if its argument isn’t a Float:

Float(“1.0”) is okay.
Float(“1”) is okay.
Float(“x”) raises ArgumentError.

ole __ wrote, On 6/20/2007 5:51 PM:

I won’t be so easily converted. It’s more characters, the character is a
stretch on the keyboard and they are harder to read. Underscores seem
backward to me.

I found that you pick them up quickly and it isn’t any harder than
reaching for shift after a while - it’s just repetition that’s needed to
memorize it. Besides that, generally I think its good to stick to the
conventions of a particular community. So, when I write Java, I use
Java conventions, and when I write Ruby, I use Ruby conventions.

It was weird at first, but I picked it up in no time.

Thanks Tim and Marcel.

Would you have thought String.i? and String.f? would make more sense
than Integer() and Float(). But yeah they will probably make for a
better implementation then the regexps.

And about camelCase, it’s true, almost no one in Ruby uses
camelCase. I’d recommend just going with the flow and adoption
lowercase_and_underscored.

I won’t be so easily converted. It’s more characters, the character is a
stretch on the keyboard and they are harder to read. Underscores seem
backward to me.

Hi –

On Thu, 21 Jun 2007, Sammy L. wrote:

Besides that, generally I think its good to stick to the conventions of a
particular community. So, when I write Java, I use Java conventions, and
when I write Ruby, I use Ruby conventions.

That’s really the main point. It’s not a matter of being converted to
using or not using camelCase – it’s a matter of being converted to
the practice of following the stylistic conventions and traditions,
whatever they may be. As a cellist I like using a bow, but when I
play the piano I use my fingers :slight_smile:

David

Yes but /^\d+/ isn’t the same as /^-?\d+$/.

On 6/21/07, ole __ [email protected] wrote:

Yes but /^\d+/ isn’t the same as /^-?\d+$/.


Posted via http://www.ruby-forum.com/.

oops, well spotted, but that will not change a lot…

640/140 > cat conversions.rb && ruby conversions.rb

vim: sts=2 sw=2 tw=0 expandtab nu:

require ‘benchmark’

class String
def int?
/^-?\d+$/ === self
end

def int1?
Integer(self) rescue false
end
end
N=10_000
Benchmark.bmbm do
|bench|
bench.report( “reg” ) { N.times{ |n| n.to_s.int?; “#{n}x”.int? } }
bench.report( “Int” ) { N.times{ |n| n.to_s.int1?; “#{n}x”.int1? } }
end

Rehearsal ---------------------------------------
reg 0.160000 0.000000 0.160000 ( 0.188396)
Int 0.440000 0.000000 0.440000 ( 0.467686)
------------------------------ total: 0.600000sec

      user     system      total        real

reg 0.160000 0.000000 0.160000 ( 0.193306)
Int 0.430000 0.010000 0.440000 ( 0.465137)

On 6/21/07, ole __ [email protected] wrote:

Thanks Tim and Marcel.

Would you have thought String.i? and String.f? would make more sense
than Integer() and Float().
They are just not the same,
String#i? and String#f? which I would call String#int? and
String#float? might be nice for you. You can search the Ruby Change
Requests if this was braught up already.
It might be a nice thing to have a String#int? without converting
actually.
But yeah they will probably make for a
better implementation then the regexps.

Hmm not sure at all, let us see

637/137 > cat conversions.rb && ruby conversions.rb

vim: sts=2 sw=2 tw=0 expandtab nu:

require ‘benchmark’

class String
def int?
/^\d+/ === self
end

def int1?
Integer(self) rescue false
end
end
N=10_000
Benchmark.bmbm do
|bench|
bench.report( “reg” ) { N.times{ |n| n.to_s.int?; “#{n}x”.int? } }
bench.report( “Int” ) { N.times{ |n| n.to_s.int1?; “#{n}x”.int1? } }
end

Rehearsal ---------------------------------------
reg 0.160000 0.000000 0.160000 ( 0.201496)
Int 0.420000 0.000000 0.420000 ( 0.466641)
------------------------------ total: 0.580000sec

      user     system      total        real

reg 0.180000 0.000000 0.180000 ( 0.238369)
Int 0.420000 0.010000 0.430000 ( 0.513518)

actually the arithmetic part is too costy :wink:

Cheers
Robert
–You see things; and you say Why?
But I dream things that never were; and I say Why not?
– George Bernard Shaw