Search code examples
c#regexnumericadditionsubtraction

Regular expression for single number or groups with addition (+) and subtraction (-) mathematical operator


I need to create a regular expression that only accepts numbers and addition and subtraction characters.

I've defined the single number and groups pattern by this way ([1-9][0-9]*)

I'm not able to add the definition for addition and subtraction characters.

I'd like to have all ok with something similar this example

Ex: 12 + 1 - 23 - 9 + 10


Solution

  • To achieve validation, I would recommend you tokenize it, but organize it by looking for an operator [+-] first then the number. Once tokenized you can verify in code if all operations are valid and accumulate a resultant total.

    Example

    var data = "12 + 1 - 23 - 9 + 10";
    
    var pattern = @"(?<Operator>[+-]*)\s*(?<Number>\d+)";
    
    var tokens =
       Regex.Matches(data, pattern)
            .OfType<Match>()
            .Select (mt => new
                 {
                     Operator = string.IsNullOrEmpty(mt.Groups["Operator"].Value)
                                      ? "+"   // Default to '+' if not found. (First Number)
                                      : mt.Groups["Operator"].Value,
                     Value    = mt.Groups["Number"].Value
                 });
    

    Result To Accumulate

    enter image description here

    Note it would also work if the numbers start out negative such as -12 + 1 - 23 - 9 + 10 result:

    enter image description here


    Frankly one could be adding negative numbers. Here is a pattern to handle the sign of the number and process the sign and the operator together to determine and positive or negative accumulation:

    var data = "-12 + 1 + -2 - -3";
    
    var pattern = @"(?<Operator>[+-]*)\s*(?<Sign>[-]*)\s*(?<Number>\d+)";
    
    var tokens =
       Regex.Matches(data, pattern)
            .OfType<Match>()
             .Select (mt => new
                      {
                        Operator = string.IsNullOrEmpty(mt.Groups["Operator"].Value)
                                         ? 1   // default to + if not found (First Number)
                                         : mt.Groups["Operator"].Value == "-" ? 0 : 1,
                        Sign     = string.IsNullOrEmpty(mt.Groups["Sign"].Value)
                                         ? 1   // default to positive
                                         : 0,
                        Value    = mt.Groups["Number"].Value
                      })
             .Select (token => new
                  {
                      Postive = (((token.Operator & token.Sign) > 0) || 
                                 ((token.Operator + token.Sign) == 0)) 
                                 ? "+" : "-",
                      Value = token.Value
                   })
    

    Result To Accumulate

    enter image description here

    Note that minus a -3 makes it a +3 when accumulated. ;-)


    For completeness, here is a snapshot of the first Select before the operator and sign determination of the following second Select is done:

    enter image description here

    Which shows that two zeros signify two minuses, which need to be converted to a plus.