Reputation: 6241
What is the regular expression to check a cost has been provided correctly:
Possible matches are:
9 | 23.3 | 25.69
Not allowed:
Upvotes: 2
Views: 515
Reputation: 108109
Since you're in Rails, you might be better served using validates_numericality_of
in your model:
validates_numericality_of :cost, :greater_than_or_equal_to => 0.01,
:less_than_or_equal_to => 0.99
To prevent fractional pennies, use this in conjunction with validates_format_of
:
validates_format_of :cost, :with => /\A\d*(\.\d{1,2})?\Z/
This leverages the strength of each validation.
Upvotes: 0
Reputation: 336418
Of course, the correct way would be to take the provided string, convert it to a number (catching errors if it's not a parseable number) and then compare that with the valid values.
If it has to be a regex, it's of course possible but ugly:
^(?:[1-9][0-9]?(?:\.[0-9]{1,2})?|0?.0[1-9]|0?.[1-9][0-9]?)$
Explanation:
^ # start of string
(?: # either match
[1-9][0-9]? # a number between 1 and 99
(?:\.[0-9]{1,2})? # optionally followed by a decimal point and up to two digits
| # or
0?.0[1-9] # a number between 0.01 and 0.09 (optionally without leading 0)
| # or
0?.[1-9][0-9]? # a number between 0.1 and 0.99
) # end of alternation
$ # end of string
Of course, in most regex dialects, you can use \d
in place of [0-9]
without a change in meaning, but I think in this case sticking to the longer version helps readability.
In Ruby, assuming your input string never contains a newline:
if subject =~ /^(?:[1-9][0-9]?(?:\.[0-9]{1,2})?|0?.0[1-9]|0?.[1-9][0-9]?)$/
# Successful match
else
# Match attempt failed
end
Since you care about the number of significant digits, another solution would be to first check if the input looks like a number, and if it passes that test, convert it to a float and check if it's in range.
^(\d{1,2}|\d{0,2}\.\d{1,2})$
would match any number (integer or decimal up to two digits after the decimal point) between 0 and 99.99. Then you just need to check whether the number is >= 0.01. The advantage of this approach is that you can easily extend the range of digits allowed before/after the decimal point if the requirements for valid numbers change, and then adjust the value check accordingly.
Upvotes: 2
Reputation: 2761
A solution using a regexp would be hard to maintain since it is a very strange and unintuitive way to solve the problem. It would be hard for anyone reading your code (including yourself in a couple of weeks) to understand what the purpose of the check is.
That said, assuming values 0.00 - 99.99 are valid, the regexp could be
^\d{0,2}(\.\d\d?)?$
Assuming 0.01 - 99.99, it's a bit more complicated:
^0{0,2}(\.(0[1-9]|[1-9]\d?))?|\d{0,2}(\.\d\d)?$
And don't get me started on 0.02 - 99.98... :-)
So basically, don't do this. Convert the string to a numerical value and then do a regular interval check.
Upvotes: 2
Reputation: 5540
try
^\d{1,2}(\.\d{1,2})?$
it checks whether there are 1 or 2 digits and optionally if there is a dot it checks if there are 1 or 2 digits after the dot.
as answer to the comments of your question: nothing speaks against checking for the format before sending the request to a server or something else. range checks could be done somewhere else.
Upvotes: 0
Reputation: 55499
I am not sure you need to do this using regular expression why dont you just split the string on '|' into an array and check each element in array is greater than 0.01 and less than 99.99
Upvotes: 2