Answered by:
regular expression for decimal range from -23 to +23 in 0.5 increments.

Question
-
-23 to +23 in 0.5 increments
Valid values = 3, -2.5, -2, -1.5, -0.5, 0, 0.5, 1, 1.5
Not valid = 2.2,-21.3
Tuesday, October 25, 2011 7:00 PM
Answers
-
@Ron, Actually I did include -23 and +23 and -23.0 and +23.0 using the prefix:
^-?(23(\.0)?
@Link, No please don't use double for things that need to be precise. If our case were to accept 10.1, it would break instantly, as .1 cannot correctly be expressed in a double format.
If needed suffix the %0.5 with an M to ensure the 0.5 stays in decimal format:
using System; using System.Globalization; namespace ValidateDecimal { class Program { static void Main(string[] args) { string values = "3, -2.5, -2, -1.5, -0.5, 0, 0.5, 1, 1.5, 2.2, -21.3"; foreach (string s in values.Split(',')) Console.WriteLine("Value={0}, IsValid={1}", s, Validate(s)); Console.ReadKey(); } static bool Validate(string s) { decimal d = -999; if (decimal.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out d)) return d >= -23 && d <= 23 && d % 0.5M == 0; return d != -999; } } }
a different approach is to multiply the result by 10, then use mod 5, to forego the 0.5M requirement.
My blog: http://blog.jessehouwing.nl/- Proposed as answer by Jesse HouwingMVP Wednesday, October 26, 2011 5:23 PM
- Marked as answer by Paul Zhou Wednesday, November 2, 2011 5:08 AM
Wednesday, October 26, 2011 5:23 PM
All replies
-
Tuesday, October 25, 2011 7:54 PM
-
Or simply use a mathematical solution, which is probably easier to read and quite a bit faster:
decimal value = 0;
if (decimal.TryParse(input, .... , out value))
return value >= -23 && value <= 23 && value %0.5 = 0;Or the simplified version of the above expression:
^-?(23(\.0)?|(2[0-2]|1?[0-9])(\.[05])?)$
Which also allows: 3.0, or
^-?(23|(2[0-2]|1?[0-9])(\.[5])?)$
Which does allow 3.5, but disallows 3.0
My blog: http://blog.jessehouwing.nl/Tuesday, October 25, 2011 10:09 PM -
Although your math solution is probably the best, I note that neither of our regexes will accept 23.0 or -23.0. Since I am into minimizing my time in developing the solution, I would just add that on as an alternative:
-?\b(?:(?:2[0-2]|[01]?\d)\.[05])\b|(?<!\.)\b(?:(?:2[0-3]|[01]?\d))\b(?!\.)|-?\b23\.0\b
And again, it can be simplified.
RonTuesday, October 25, 2011 11:22 PM -
And here is a more compact version of the above:
-?(?<!\.)\b(?:(?:23(?:\.0)?)|(?:(?:2[0-2]|[1]?\d)(?:\.[05])?))\b(?!\.)
Or with free-spacing enabled:
-?(?<!\.)\b
(?:(?:23(?:\.0)?)|
(?:(?:2[0-2]|[1]?\d)
(?:\.[05])?))
\b(?!\.)I note a particular difference between your regex and mine in that mine should be able to detect the value any place in the string. I don't know if that is important to the OP or not.
Ron- Proposed as answer by Jesse HouwingMVP Wednesday, October 26, 2011 5:24 PM
Wednesday, October 26, 2011 1:20 AM -
@Jesse, It is more appropriate to use the double value type. I think that "value % 0.5" is incorrect for decimal type.
using System; using System.Globalization; namespace ValidateDecimal { class Program { static void Main(string[] args) { string values = "3, -2.5, -2, -1.5, -0.5, 0, 0.5, 1, 1.5, 2.2, -21.3"; foreach (string s in values.Split(',')) Console.WriteLine("Value={0}, IsValid={1}", s, Validate(s)); Console.ReadKey(); } static bool Validate(string s) { double d = -999; if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out d)) return d >= -23 && d <= 23 && d % 0.5 == 0; return d != -999; } } }
Kind regards,
aelassas.free.frWednesday, October 26, 2011 4:49 PM -
@Ron, Actually I did include -23 and +23 and -23.0 and +23.0 using the prefix:
^-?(23(\.0)?
@Link, No please don't use double for things that need to be precise. If our case were to accept 10.1, it would break instantly, as .1 cannot correctly be expressed in a double format.
If needed suffix the %0.5 with an M to ensure the 0.5 stays in decimal format:
using System; using System.Globalization; namespace ValidateDecimal { class Program { static void Main(string[] args) { string values = "3, -2.5, -2, -1.5, -0.5, 0, 0.5, 1, 1.5, 2.2, -21.3"; foreach (string s in values.Split(',')) Console.WriteLine("Value={0}, IsValid={1}", s, Validate(s)); Console.ReadKey(); } static bool Validate(string s) { decimal d = -999; if (decimal.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out d)) return d >= -23 && d <= 23 && d % 0.5M == 0; return d != -999; } } }
a different approach is to multiply the result by 10, then use mod 5, to forego the 0.5M requirement.
My blog: http://blog.jessehouwing.nl/- Proposed as answer by Jesse HouwingMVP Wednesday, October 26, 2011 5:23 PM
- Marked as answer by Paul Zhou Wednesday, November 2, 2011 5:08 AM
Wednesday, October 26, 2011 5:23 PM -
@Ron, Actually I did include -23 and +23 and -23.0 and +23.0 using the prefix:
^-?(23(\.0)?
Weird. I tested without looking too closely at the regex itself and thought it didn't return that. Sorry.
RonWednesday, October 26, 2011 7:31 PM -
No please don't use double for things that need to be precise. If our case were to accept 10.1, it would break instantly, as .1 cannot correctly be expressed in a double format.
Yes, you're completely right! I've noticed that the validate method may return true if the string parameter s does not pass the TryParse method because the d will get 0.00... as value and will pass the test d != -999. I've rewritten it in a more logical way.static bool Validate(string s) { decimal d; if (decimal.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out d)) return d >= -23 && d <= 23 && (d * 10) % 5M == 0; else return false; }
aelassas.free.frWednesday, October 26, 2011 9:57 PM