1

Let's say I get some input as a string, and I would like to know whether it contains an Integer or a Float.

For example:

input_1 = "100"
input_2 = "100.0123"

Now, let's take into account the following:

input_1.respond_to?(:to_f) # => true 
input_1.is_a?(Float)       # => false
input_1.is_a?(Fixnum)      # => false
input_1.to_f?              # => 100.0

input_2.respond_to?(:to_i) # => true
input_2.is_a?(Integer)     # => false
input_2.is_a?(Fixnum)      # => false
input_2.to_i               # => 100

In the cases above, we can't actually determine whether the string contains an Integer or a Float. Is there a way in Ruby to determine whether a string contains a Fixnum or Float?

Ajedi32
  • 45,670
  • 22
  • 127
  • 172
user2840647
  • 1,236
  • 1
  • 13
  • 32
  • You could always just test to see if the string has a "." in it. BTW, do you want "100.00" to be counted as an integer or a float? – Adrian Jul 22 '15 at 16:38
  • @Adrian that would be counted as a float. – user2840647 Jul 22 '15 at 16:44
  • 2
    "1.3" is contained in "ab1.3cd". Is that what you mean, or do you want to know if your string `str` equals the representation of an integer or float (i.e, does there exist an integer or float `n` such that `n.to_s == str`)? – Cary Swoveland Jul 22 '15 at 16:57
  • Will your "strings" always be ONLY the value (`"123"` or `"1.23"`) or will the value be embedded inside non-digits (`"ab 1.23 cd"`)? – the Tin Man Jul 22 '15 at 16:58
  • 1
    Why the rush selecting an answer?? I expect others are still working on solutions. Also, kindly answer the questions raised in the comments (by editing your question). – Cary Swoveland Jul 22 '15 at 17:09
  • The best way is to convert it to the target class and catch any exception – SwiftMango Jul 22 '15 at 17:20

4 Answers4

7

The correct way to do this is the Integer and Float methods.

Integer("100")
100
Integer("1.03")
# ArgumentError: invalid value for Integer(): "1.03"
Float("1.03")
1.03
Float("1.2e9")
1200000000.0
Float("100")
100.0

You can make methods out of these like so:

class String
  def is_int?
    Integer(self) && true rescue false
  end

  def is_float?
    Float(self) && true rescue false
  end
end
Max
  • 21,123
  • 5
  • 49
  • 71
0

Something like this should capture the various ways of expressing numbers as strings:

%w[
  1
  1.0
  0xDEADBEEF
  0b1010
  1e10
  1.2e10
  -1
  -1.2
  a1
  a1.0
].each do |str|
  type = begin
           :integer if Integer(str)
         rescue ArgumentError
           begin
            :float if Float(str)
           rescue ArgumentError
            :neither
           end
         end
  type # => :integer, :float, :integer, :integer, :float, :float, :integer, :float, :neither, :neither
end
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
0

If the string is the representation of an integer or float (ie., if the string str can be obtained by converting an integer or float to str):

def integer_or_float?(str)
  :integer if Integer(str) rescue :float
end

integer_or_float? "-123"  #=> :integer
integer_or_float? "12.3"  #=> :float
integer_or_float? "1.2e9" #=> :float

If the string may not be the representation of an integer or float:

def integer_or_float?(str)
  :integer if Integer(str) rescue (:float if Float(str) rescue nil)
end

integer_or_float? "-123"  #=> :integer
integer_or_float? "12.3"  #=> :float
integer_or_float? "1.2e9" #=> :float
integer_or_float? "1.2x"  #=> :nil
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
-1

You could use regular expressions:

n = '100.0'

if n =~ /\A\d+\z/
  puts 'integer'
elsif n =~ /\A\d+\.\d+\z/
  puts 'float'
else
  puts 'not integer or float'
end

Edit regular expressions to taste.

Adrian
  • 14,931
  • 9
  • 45
  • 70