I am making a simple numeric expression solver using regexes and right now I'm working at splitting polynomials into its terms. So this is what I got so far:
(.*?)([\+-](.*?))+
This doesn't work when negative numbers are involved. Take 3*-2+1 as an example: the terms I get are 3*, -2 and +1, which is obviously wrong.
I thought I could get away with a negative look behind before the sign so that signs preceded by * or / are discarded:
(.*?)((?<![\*/])[\+-](.*?))+
But this doesn't even work with positive numbers
Suggestions?
Hope you didn't spend a lot of time creating your own parser ;)
I use this code to evaluate expressions:
class Program
{
public static double Evaluate(string expression)
{
using (var stringReader = new StringReader("<dummy/>"))
{
var navigator = new XPathDocument(stringReader).CreateNavigator();
expression = Regex.Replace(expression, #"([\+\-\*])", " ${1} "); // add some space
expression = expression.Replace("/", " div ").Replace("%", " mod ");
return (double)navigator.Evaluate(string.Format("number({0})", expression));
}
}
static void Main(string[] args)
{
Console.WriteLine(Evaluate("3*-2+1"));
}
}
Will output: -5
It is based on the XPathNavigator.Evaluate method. The Regex adds some spaces to the input and then division and modulo symbol are replaced.
Related
Overview of Project:
I am creating a multi form application, which consist of two forms and one parent class. Both Forms have a series of validation functions, such as isLetter() isNumber() and isValidEmail(). My Issue comes when using the isNumber() Function.
public static bool numValidation(string strNum)
{
if (!string.IsNullOrWhiteSpace(strNum))
{
int temp;
if (int.TryParse(strNum, out temp))
{
Console.WriteLine("Phone Number is a valid input: " + temp);
return true;
}
else
{ Console.WriteLine(temp + "Is not Valid input!!"); }
}
return false;
}
At first glance it works fine but once I tried to break it, I realised that when an actual phone number is entered I get an error saying that the number is too high. Any ideas how to get round this constraint ? as the only reason I need this validation is for phone numbers, Fax etc. I simply need this function to accept very large numbers such as phone numbers
I suggest that you use a regular expresion to validate the input in your case
public static bool numValidation(string strNum)
{
Regex regex = new Regex(#"^[0-9]+$");
return (regex.IsMatch(strNum)) ;
}
Parsing a string and not using that value is not really needed.
For more details checkout this answers - Regex for numbers only
From Mauricio Gracia Gutierrez answer
I suggest that you use a regular expresion to validate the
input in your case
public static bool numValidation(string strNum) {
Regex regex = new Regex(#"^[0-9]+$");
return (regex.IsMatch(strNum)) ; } Parsing a string and not using that value is not really needed.
For more details checkout this answers - Regex for numbers only
You could enhance the expression to check the length of the number:
Between 5 and 10 digits:
Regex regex = new Regex(#"^[\d]{5,10}+$");
Max 10 digits:
Regex regex = new Regex(#"^[\d]{10}+$");
At least 5 digits:
Regex regex = new Regex(#"^[\d]{5,}+$");
I have code to remove trailing zeros from a value before presenting it to the UI, however I have found that in some cases, instead of removing the zeros it alters the value.
eg: 123.400000000000000000 becomes 123.40000000000001
the code I am using is:
string value = "123.400000000000000000";
value = double.Parse(value).ToString("G29");
Does anyone know why this is happening, and how I can alter my code so it shows '123.4' instead.
It's because you're turning it into a double and, as everyone who's spent time dealing with floating point values will know, double precision values are not infinite precision values. The value selected is as close as it can get to what you provide but that's not always exactly what you want.
If you have a numeric-style string that you want to strip trailing zeros from, why don't you just strip the trailing zeros from it, with something like:
if (s.Contains(".")) {
Regex regex = new Regex("\\.?0*$");
s = regex.Replace(s,"");
}
The check for a . character is to ensure you don't strip trailing zeros off a number like 1000. Once you know there's a decimal point in there, zeros (and the decimal point itself if it's _all zeros after that) can be stripped off the end with impunity. You can see it in action in the following complete console program:
using System;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static string StripZ(string s)
{
if (s.Contains("."))
{
Regex regex = new Regex("\\.?0*$");
s = regex.Replace(s, "");
}
return s;
}
static void Main(string[] args)
{
Console.WriteLine(StripZ("123.400"));
Console.WriteLine(StripZ("3.0"));
Console.WriteLine(StripZ("7."));
Console.WriteLine(StripZ("1000"));
Console.ReadLine();
}
}
}
The output of that program is:
123.4
3
7
1000
The problem is that 123.4 is not exactly representable in a binary floating point data type. The closest double precision value is:
123.40000 00000 00005 68434 18860 80801 48696 89941 40625
The ToString method is rounding that to
123.40000 00000 0001
You should use a decimal data type instead of a binary data type. For instance:
string value = "123.400000000000000000";
value = decimal.Parse(value).ToString("G29");
However, if you are really starting with a string, and just wish to trim trailing zeros then it would perhaps be more prudent to do that using text processing.
I have a function which creates Regex string for validating decimal.
public static string DecimalWithPlaces(int wholePart, int fractionalPart)
{
return #"^-?[0-9]{0," + wholePart + #"}\.[0-9]{1," + fractionalPart + #"}$";
}
Could anyone let me know how can I excluding zero from this?
For example: "0", "0.0","0.00" etc should not be matched.
Thanks
Amy's right - examples would be good.
However, I'm going in blind.
Did you want to exclude all zeros, or just the value of zero?
To exclude zeros, try this and see what happens.
public static string DecimalWithPlaces(int wholePart, int fractionalPart)
{
return #"^-?[1-9]{0," + wholePart + #"}\.[1-9]{1," + fractionalPart + #"}$";
}
To exclude the number zero... That's actually not a good check for regex. That's a value check.
In my books you should be using TWO validation steps on the value. One to check that it meets your precision/scale requirements as per your regex above, the second to then check it for nonzero value.
I do believe that using regex for the zero value thing is possible. But I strongly advise against it. That said, if you're committed to ignoring that reccomendation then you'll probably want to look into Negative Lookahead regex structures.
I have some strings like below:
string num1 = "D123_1";
string num2 = "D123_2";
string num3 = "D456_11";
string num4 = "D456_22";
string num5 = "D_123_D";
string num5 = "_D_123";
I want to make a function that will do the following actions:
1- Checks if given string DOES HAVE an Underscore in it, and this underscore should be after some Numbers and Follow with some numbers: in this case 'num5' and 'num6' are invalid!
2- Replace the numbers after the last underscore with any desired string, for example I want 'num1 = "D123_1"' to be changed into 'D123_2'
So far I came with this idea but it is not working :( First I dont know how to check for criteria 1 and second the replace statement is not working:
private string CheckAndReplace(string given, string toAdd)
{
var changedString = given.Split('_');
return changedString[changedString.Length - 1] + toAdd;
}
Any help and tips will be appriciated
What you are looking for is a regular expression. This is (mostly) from the top of my head. But it should easily point you in the right direction. The regular expression works fine.
public static Regex regex = new Regex("(?<character>[a-zA-Z]+)(?<major>\\d+)_(?<minor>\\d+)",RegexOptions.CultureInvariant | RegexOptions.Compiled);
Match m = regex.Match(InputText);
if (m.Succes)
{
var newValue = String.Format("{0}{1}_{2}"m.Groups["character"].Value, m.Groups["major"].Value, m.Groups["minor"].Value);
}
In your code you split the String into an array of strings and then access the wrong index of the array, so it isn't doing what you want.
Try working with a substring instead. Find the index of the last '_' and then get the substring:
private string CheckAndReplace(string given, string toAdd) {
int index = given.LastIndexOf('_')+1;
return given.Substring(0,index) + toAdd;
}
But before that check the validity of the string (see other answers). This code fragment will break when there's no '_' in the string.
You could use a regular expression (this is not a complete implementation, only a hint):
private string CheckAndReplace(string given, string toAdd)
{
Regex regex = new Regex("([A-Z]*[0-9]+_)[0-9]+");
if (regex.IsMatch(given))
{
return string.Concat(regex.Match(given).Groups[1].Value, toAdd);
}
else
{
... do something else
}
}
Use a good regular expression implementation. .NET has standard implementation of them
Is there a nice way to evaluate a regular expression range, say, for a url such as
http://example.com/[a-z]/[0-9].htm
This would be converted into:
http://example.com/a/0.htm
http://example.com/a/1.htm
http://example.com/a/2.htm
...
http://example.com/a/9.htm
...
http://example.com/z/0.htm
http://example.com/z/1.htm
http://example.com/z/2.htm
...
http://example.com/z/9.htm
I've been scratching my head about this, and there's no pretty way of doing it without going through the alphabet and looping through numbers.
Thanks in advance!
If you really need to do this, it's not that hard to generate the strings using recursion. Here's a snippet to do just that in Java:
public class Explode {
static void dfs(String prefix, String suffix) {
final int k = suffix.indexOf('[');
if (k == -1) {
System.out.println(prefix + suffix);
} else {
prefix += suffix.substring(0, k);
char from = suffix.charAt(k+1);
char to = suffix.charAt(k+3);
suffix = suffix.substring(k+5);
for (char ch = from; ch <= to; ch++) {
dfs(prefix + ch, suffix);
}
}
}
public static void main(String[] args) {
String template = "http://example.com/[a-c]/[0-2][x-z].htm";
dfs("", template);
}
}
(see full output)
This is a standard recursive tuple generator, but with some string infixing in between. It's trivial to port to C#. You'd want to use a mutable StringBuilder-like class for better performance.
I guess there is no way to expand regular expressions in general. Your example
http://foo.com/[a-z]/[0-9].htm
is a very easy regex without * or + for instance. How would you expand such a regex?
In your case you might get away with some loops, but as I said - this is a untypical (easy) regex.