I have a function as below (I am not to much familiar with linq)
public static bool IsNumber(string s, char dec_sep)
{
return s.Length > 0 && s.All(c => Char.IsDigit(c));
}
If the number contains a decimal separator I get false as a fact.
I want to check if my defined decimal separator is in the number
Is it possible modify this function for this purpose ?
Or should I write another function ?
For being more clear
If in the string there ise decimal separator such as 72.5 it returns false (my defined separator is "." ). It already returns true if the string is 72 or 725.
I want this function returns TRUE even with a decimal separator.
I would advise against writing your own "IsNumber" function.
The framework already has TryParse of all built in value types - so I suggest using either float.TryParse, double.TryParse or decimal.TryParse depending on the size and precision of number you're expecting (23, 64 or 128 bit).
Writing your own "IsNumber" function is bound to have some difficulties, especially if you're going to attempt to parse user input (or any input you can't control, for that matter) - because like many other "simple" things, numbers are nothing but simple.
First, Numbers can have a thousands separator - in English, 1,234.56 is a valid number.
Second, string representations of numbers are culture dependent - 1,234.56 is invalid in some cultures - where the decimal separator is a comma and the thousands separator is a dot - so you would actually write it like this: 1.234,56
Note that these are two different ways to write the same number -
one thousand, two hundred thirty-four and fifty-six hundredths.
Even worst, you can write the same number in different numerals altogether - Thai, Arabic, Chinese or Hebrew - all of these languages (and probably many more languages) have their own symbols for numbers - and I'm not sure that IsDigit covers them all (though it's probably culture dependent also).
Having said all that, your current function will throw a NullReferenceException if the string is null - the very least you should do is either throw an ArgumentNullException or simply return false if the string is null.
Further more, there are going to be valid use-case where you want to know if a char exists exactly zero or once in a string - one way to do it is by subtracting IndexOf from LastIndexOf and check that the result of this subtruction is 0.
To combine that with your current method, you also want to change the condition in the All method to allow the char to either be a digit or your designated decimal separator.
If you really have to write your own method, here's how I would start it:
public static bool IsNumber(string s, char dec_sep)
{
return !string.IsNullOrEmpty(s)
&& s.LastIndexOf(dec_sep) - s.IndexOf(dec_sep) == 0
&& s.All(c => Char.IsDigit(c) || c == dec_sep);
}
The first condition will return false if the string is null or empty,
the second one will return false only if the string contains dec_sep more than once,
and the third will return false only if the string contains any char that is neither a digit nor dec_sep.
If you are a fan of regex you can also try "^\\d+\\.??(\\d*)?$"
Related
What regex i can use for positive numeric and decimal values ?
Accepted values: 0, 22.5 , 0.35 , 89 , .38
Invalid values : -22 , -.25 , -0.66 , abc, -22abc, 55er
I have tried this but i get error
^\d*\.?\d*[1-9]+\d*$)|(^[1-9]+\d*\.\d*$"
Too many )'s
^\d*\.?\d*[1-9]+\d*$)|(^[1-9]+\d*\.\d*$
You're missing a closing ) in the regex.
^\d*\.?\d*[1-9]+\d*$)|(^[1-9]+\d*\.\d*)$
However, I'd strongly suggest you look at Decimal.TryParse instead of trying to validate numbers using the format of a string yourself.
I would simply your pattern to this:
\d*(?:\.\d+)?
Demo
This seems to cover all your positive decimal number use cases. The decimal component is optional, meaning that the pattern covers integers. Decimal numbers are covered, and also numbers which only have a decimal component.
Note that you might have to surround the pattern with ^$ anchors, depending on the particular API you are using.
Edit:
If you also need to ensure that empty string is not matched, then we can add a lookahead to the above pattern:
(?=.)\d*(?:\.\d+)?
Demo
Or, if you want to stay away from Regex, one of these might work:
private static bool IsPositiveDecimal(string decimalString)
{
return decimal.TryParse(decimalString, out var aDecimal) && aDecimal >= 0;
}
or
private static bool TryParsePositiveDecimal(string decimalString, out decimal aDecimal)
{
return decimal.TryParse(decimalString, out aDecimal) && aDecimal >= 0;
}
If you feed the latter one a non-positive decimal, it will return false, but will return the parsed decimal in the out parameter.
This should suit your needs without injecting a complicated Regex into your code.
I believe this regex should meet all the cases and will only match valid samples and discard all invalid ones.
^(?:[1-9]\d*(\.\d+)?|0?\.\d+|0)$
Regex Explanation:
^ - Start of string
(?: - Start of non capture group
[1-9]\d* - Matches a number without unneeded preceding zeroes. Will invalidated 01 or 001
(\.\d+)? - Can optionally have decimal part
| - Alternation
0?\.\d+ - Allows only decimal numbers that can optionally have zero before them. E.g. to support numbers like 0.11 or .11
| - Alternation
0 - Supporting literal zero as a special case
) - closing of non-capture group
$ - End of string
Demo
^\d*\.?\d+$
There will also match 0.00 .00 0.0
Why is it when I'm parsing a decimal (0) ToString my string shows as empty when using the method:
String somthing = someDecimal.ToString("#")
And when I'm using:
String somthing = somDecimal.ToString("0.##")
The string shows up as 0?
When I'm looking at the value in the debug mode in both way it's says they have a "0" in them.
From The "#" Custom Specifier
Note that this specifier never displays a zero that is not a
significant digit, even if zero is the only digit in the string. It
will display zero only if it is a significant digit in the number that
is being displayed.
If you want to display digits after your decimal point, you need to use 0.00 instead of 0.##.
Because pound "#" means convert to symbol if there is a number. 0 is an "empty" number, so it converts to "".
In fact, in second case, you get 0, as you imply to show at least one digit before dot.
This all is by design convention of C# language.
MSDN: the "#" Custom Specifier
The "#" custom format specifier serves as a digit-placeholder symbol.
If the value that is being formatted has a digit in the position where
the "#" symbol appears in the format string, that digit is copied to
the result string. Otherwise, nothing is stored in that position in
the result string. Note that this specifier never displays a zero that
is not a significant digit, even if zero is the only digit in the
string. It will display zero only if it is a significant digit in the
number that is being displayed.
So if the decimal would be 1 instead of 0 it would be diplayed even with ToString("#").
If you want a fixed number of decimals after the decimal point, you need to use
String somthing = somDecimal.ToString("0.00")
In your example you use the # specifier which means 'put here a number if there is a meaningful number'.
It would work if someDecimal is 0.01
decimal somDecimal = 0.01m
String somthing = somDecimal.ToString("0.##");
but not if
decimal somDecimal = 0.01m
String somthing = somDecimal.ToString("0.#");
I must have strings in the format x:y where x and y have to be five digits (zero padded) and x <= y.
Example:
00515:02152
What Regex will match this format?
If possible, please explain the solution briefly to help me learn.
EDIT: Why do I need Regex? I've written a generic tool that takes input and validates it according to a configuration file. An unexpected requirement popped up that would require me to validate a string in the format I've shown (using the configuration file). I was hoping to solve this problem using the existing configuration framework I've coded up, as splitting and parsing would be out of the scope of this tool. For an outstanding requirement such as this, I don't mind having some unorthodox/messy regex, as long as it's not 10000 lines long. Any intelligent solutions using Regex are appreciated! Thanks.
Description
This expression will validate that the first 5 digit number is smaller then the second 5 digit number where zero padded 5 digit numbers are in a : delimited string and is formatted as 01234:23456.
^
(?:
(?=0....:[1-9]|1....:[2-9]|2....:[3-9]|3....:[4-9]|4....:[5-9]|5....:[6-9]|6....:[7-9]|7....:[8-9]|8....:[9])
|(?=(.)(?:0...:\1[1-9]|1...:\1[2-9]|2...:\1[3-9]|3...:\1[4-9]|4...:\1[5-9]|5...:\1[6-9]|6...:\1[7-9]|7...:\1[8-9]|8...:\1[9]))
|(?=(..)(?:0..:\2[1-9]|1..:\2[2-9]|2..:\2[3-9]|3..:\2[4-9]|4..:\2[5-9]|5..:\2[6-9]|6..:\2[7-9]|7..:\2[8-9]|8..:\2[9]))
|(?=(...)(?:0.:\3[1-9]|1.:\3[2-9]|2.:\3[3-9]|3.:\3[4-9]|4.:\3[5-9]|5.:\3[6-9]|6.:\3[7-9]|7.:\3[8-9]|8.:\3[9]))
|(?=(....)(?:0:\4[1-9]|1:\4[2-9]|2:\4[3-9]|3:\4[4-9]|4:\4[5-9]|5:\4[6-9]|6:\4[7-9]|7:\4[8-9]|8:\4[9]))
)
\d{5}:\d{5}$
Live demo: http://www.rubular.com/r/w1QLZhNoEa
Note that this is using the x option to ignore all white space and allow comments, if you use this without x then the expression will need to be all on one line
The language you want to recognize is finite, so the easiest thing to do is just list all the cases separated by "or". The regexp you want is:
(00000:[00000|00001| ... 99999])| ... |(99998:[99998|99999])|(99999:99999)
That regexp will be several billion characters long and take quite some time to execute, but it is what you asked for: a regular expression that matches the stated language.
Obviously that's impractical. Now is it clear why regular expressions are the wrong tool for this job? Use a regular expression to match 5 digits - colon - five digits, and then once you know you have that, split up the string and convert the two sets of digits to integers that you can compare.
x <= y.
Well, you are using wrong tool. Really, regex can't help you here. Or even if you get a solution, that will be too complex, and will be too difficult to expand.
Regex is a text-processing tool to match pattern in regular languages. It is very weak when it comes to semantics. It cannot identify meaning in the given string. Like in your given condition, to conform to x <= y condition, you need to have the knowledge of their numerical values.
For e.g., it can match digits in a sequence, or a mix of digits and characters, but what it cannot do is the stuff like -
match a number greater than 15 and less than 1245, or
match a pattern which is a date between given two dates.
So, where-ever matching a pattern, involves applying semantics to the matched string, Regex is not an option there.
The appropriate way here would be to split the string on colon, and then compare numbers. For leading zero, you can find some workaround.
You can't generally* do this with regex. You can use regex to match the pattern and extract the numbers, then compare the numbers in your code.
For example to match such format (without comparing the numbers) and get the numbers you could use:
^(\d{5}):(\d{5})\z
*) You probably could in this case (as the numbers are always 5 digits and zero padded, but it wouldn't be nice.
You should do something like this instead:
bool IsCorrect(string s)
{
string[] split = s.split(':');
int number1, number2;
if (split.Length == 2 && split[0].Length == 5 && split[1].Length == 5)
{
if (int.TryParse(split[0], out number1) && int.TryParse(split[1], out number2) && number1 <= number2)
{
return true;
}
}
return false;
}
With regex you can't make comparisons to see if a number is bigger than another number.
Let me show you a good example of why you shouldn't try to do this. This is a regex that (nearly) does the same job.
https://gist.github.com/anonymous/ad74e73f0350535d09c1
Raw file:
https://gist.github.com/anonymous/ad74e73f0350535d09c1/raw/03ea835b0e7bf7ac3c5fb6f9c7e934b83fb09d95/gistfile1.txt
Except it's just for 3 digits. For 4, the program that generates these fails with an OutOfMemoryException. With gcAllowVeryLargeObjects enabled. It went on until 5GB until it crashed. You don't want most of your app to be a Regex, right?
This is not a Regex's job.
This is a two step process because regex is a text parser and not analyzer. But with that said, Regex is perfect for validating that we have the 5:5 number pattern and this regex pattern will determine if we have that form factor \d\d\d\d\d:\d\d\d\d\d right. If that form factor is not found then a match fails and the whole validation fails. If it is valid, we can use regex/linq to parse out the numbers and then check for validity.
This code would be inside a method to do the check
var data = "00515:02151";
var pattern = #"
^ # starting from the beginning of the string...
(?=[\d:]{11}) # Is there is a string that is at least 11 characters long with only numbers and a ;, fail if not
(?=\d{5}:\d{5}) # Does it fall into our pattern? If not fail the match
((?<Values>[^:]+)(?::?)){2}
";
// IgnorePatternWhitespace only allows us to comment the pattern, it does not affect the regex parsing
var result = Regex.Matches(data, pattern, RegexOptions.IgnorePatternWhitespace)
.OfType<Match>()
.Select (mt => mt.Groups["Values"].Captures
.OfType<Capture>()
.Select (cp => int.Parse(cp.Value)))
.FirstOrDefault();
// Two values at this point 515, 2151
bool valid = ((result != null) && (result.First () < result.Last ()));
Console.WriteLine (valid); // True
Using Javascript this can work.
var string = "00515:02152";
string.replace(/(\d{5})\:(\d{5})/, function($1,$2,$3){
return (parseInt($2)<=parseInt($3))?$1:null;
});
FIDDLE http://jsfiddle.net/VdzF7/
I want to create regex in c# which return true for value having blank/space/null or decimal value with 2 decimal points.So not to accept other than that.
Although probably not the most efficient, this regular expression should do what you want:
^((\d+[\.]\d{2})|([\.]\d{2})|()|\s*)$
It requires any decimal number to have two decimal places, but it does accept either 0.99 or .99 as an example.
If you want to allow users to enter in 9 or 9.0 or 9.01 (that is, not force the user to enter in two decimal places) you can just modify the above like this:
^((\d+([\.]\d{0,2})*)|([\.]\d{0,2})|()|\s*)$
It is just setting the quantifiers to {0,2} instead of {2}, and making the existence of decimals places optional.
^\s*(?:[+-]?\d*\.\d{2})?\s*$
matches a number with exactly two decimal places, optionally surrounded by whitespace, or the empty/whitespace only string.
use this regular expression ^(\s+)|(([+-])?\d+[,\.]\d{2})|()|(null)$
I would suggest this pattern to handle numbers and empty string scenario.
^[-+]?\d*(\.\d{2})?|\s*$
Reagrding NULL, I have experienced that when we pass null as an input in RegEx it throws ArgumentNullException. So my recommendation is to validate NULL using != operator by matching with null:
if(str != null && RegEx.IsMatch(str,#"^[-+]?\d*(\.\d{2})?|\s*$"))
// valid data
where:
str = string that contains data validating
Above pattern will also allow: -.00 or -0.00 as validate decimals.
Hi i have a senario where i have to prevent a field from entering zero by using Regex. But i have failed in creating the regex Can anybody help me in giving a correct regex?
What i have done is
^[1-9]\d{0,2}(\d*|(,\d{3})*)$
But this fails because it fails when a number contains zero like 340 is entered.
My senario is that the field must be able to accept all other integers except zero
How about this regex:
^[1-9][0-9]*$
String starts with 1 to 9 then has zero or more characters in 0 to 9.
It seems like regex might be overkill here. Why don't you try something like this:
int value;
if (Int32.TryParse(fieldString, out value))
{
if (value == 0)
{
// handle invalid value
}
}
This can be done with the pattern:
^(?![0,]+$)\d{0,2}(\d*|(,\d{3})*)$
Assuming you only want to accept positive integers. The pattern (?![0,]+$) prevents the expression from matching if it contains only zeros and commas. The second part is from the original expression, and allows the original combination of digits and commas for other values.
I assuming you'll be converting the field entry into an int? If so why not just do:
if (int == 0)
{
//not valid
}
However I'd hazard a guess you're using some kind of validation library?
You can try this one:
^[+-]?0*[1-9]\d*$
It accepts optional sign (plus or minus), then any number of leading zeroes, then at least one non-zero digit followed by any number of digits. You can see it in action at RegExr.