terence vaughn
terence vaughn

Reputation: 537

Regular expression to match number formats

I'm trying to write a small program that asks a user to input a number and the program will determine if it's a valid number. The user can enter any kind of number (integer, float, scientific notation, etc.).

My question is what regular expression should be used to keep something like "7w" from being matched as a valid number? Also I would like the number 0 to exit the loop and end the program, but as it's written now 0 is matching valid like any other number. Any insight please?

x = 1

while x != 0
  puts "Enter a string"
  num = gets

  if num.match(/\d+/)
    puts "Valid"
  else
    puts "invalid"
  end

  if num == 0
    puts "End of program"
    x = num
  end   
end

Upvotes: 2

Views: 3577

Answers (2)

thebugfinder
thebugfinder

Reputation: 334

You need to execute this script from the command line, not a text editor, as you will be prompt to enter a number.

This is the ultra compact version

def validate(n)
  if (Float(n) != nil rescue return :invalid)
    return :zero if n.to_f == 0
    return :valid
  end
end
print "Please enter a number: "
puts "#{num = gets.strip} is #{validate(num)}"

Output:

Please enter a number: 00
00 is zero

Here is a longer version that problably you can extend it to tweak it to your needs.

class String
  def numeric?
    Float(self) != nil rescue false
  end
end

def validate(n)
  if n.numeric?
    return :zero if n.to_f == 0
    return :valid
  else
    return :invalid
  end
end

print "Please enter a number: "
puts "#{num = gets.strip} is #{validate(num)}"

And here is a test for all the possible cases

test_cases = [
  "33", #int pos
  "+33", #int pos
  "-33", #int neg
  "1.22", #float pos
  "-1.22", #float neg
  "10e5", #scientific notation
  "X", #STRING not numeric
  "", #empty string
  "0", #zero
  "+0", #zero
  "-0", #zero
  "0.00000", #zero
  "+0.00000", #zero
  "-0.00000", #zero
  "-999999999999999999999995444444444444444444444444444444444444434567890.99", #big num
  "-1.2.3", #version number
  "  9  ", #trailing spaces
]

puts "\n** Test cases **"
test_cases.each do |n|
  puts "#{n} is #{validate(n)}"
end

Which outputs:

Please enter a number: 12.34
12.34 is valid

** Test cases ** 33 is valid
+33 is valid
-33 is valid
1.22 is valid
-1.22 is valid
10e5 is valid
X is invalid
 is invalid
0 is zero
+0 is zero
-0 is zero
0.00000 is zero
+0.00000 is zero
-0.00000 is zero
-999999999999999999999995444444444444444444444444444444444444434567890.99 is valid
-1.2.3 is invalid
   9   is valid

Source for the idea of checking if its numeric:

Upvotes: 2

Eugene
Eugene

Reputation: 4879

To start with, you are overcomplicating the loop, secondly, your regular expression needs to be a bit more explicit. Try something like this:

x = 1

while x != 0
  puts "Enter a string"
  num = gets.chomp
  if num == "0"
    puts "exiting with 0"
    exit 0
  elsif num.match(/^[0-9](\.[0-9])?$+/)
    puts "Valid"
  else
    puts "invalid"
  end
end

This expression will match any number that contains a digit or a decimal, and will fail to match anything containing letters. If the string entered is exactly 0, the script will exit with status 0.

Upvotes: 1

Related Questions