@@ -15,7 +15,6 @@ namespace ToolGood.Algorithm.Internals
1515{
1616 class MathVisitor : AbstractParseTreeVisitor < Operand > , ImathVisitor < Operand >
1717 {
18- private static readonly Regex sumifRegex = new Regex ( @"(<|<=|>|>=|=|==|===|!=|!==|<>) *([-+]?\d+(\.(\d+)?)?)" , RegexOptions . Compiled ) ;
1918 public event Func < string , Operand > GetParameter ;
2019 public event Func < string , List < Operand > , Operand > DiyFunction ;
2120 public int excelIndex ;
@@ -2241,8 +2240,8 @@ public virtual Operand VisitAVERAGE_fun(mathParser.AVERAGE_funContext context)
22412240
22422241 public virtual Operand VisitAVERAGEIF_fun ( mathParser . AVERAGEIF_funContext context )
22432242 {
2244- var args = new List < Operand > ( ) ;
2245- foreach ( var item in context . expr ( ) ) { var aa = item . Accept ( this ) ; if ( aa . IsError ) { return aa ; } args . Add ( aa ) ; }
2243+ var exprs = context . expr ( ) ; var args = new List < Operand > ( exprs . Length ) ;
2244+ for ( int i = 0 ; i < exprs . Length ; i ++ ) { var aa = this . Visit ( exprs [ i ] ) ; if ( aa . IsError ) { return aa ; } args . Add ( aa ) ; }
22462245
22472246 List < decimal > list = new List < decimal > ( ) ;
22482247 var o = F_base_GetList ( args [ 0 ] , list ) ;
@@ -2260,17 +2259,18 @@ public virtual Operand VisitAVERAGEIF_fun(mathParser.AVERAGEIF_funContext contex
22602259 decimal sum ;
22612260 int count ;
22622261 if ( args [ 1 ] . Type == OperandType . NUMBER ) {
2263- count = MathVisitor . F_base_countif ( list , args [ 1 ] . NumberValue ) ;
2262+ count = F_base_countif ( list , args [ 1 ] . NumberValue ) ;
22642263 sum = count * args [ 1 ] . NumberValue ;
22652264 } else {
22662265 if ( decimal . TryParse ( args [ 1 ] . TextValue . Trim ( ) , NumberStyles . Any , CultureInfo . InvariantCulture , out decimal d ) ) {
2267- count = MathVisitor . F_base_countif ( list , d ) ;
2268- sum = MathVisitor . F_base_sumif ( list , '=' + args [ 1 ] . TextValue . Trim ( ) , sumdbs ) ;
2266+ count = F_base_countif ( list , d ) ;
2267+ sum = F_base_sumif ( list , d , sumdbs ) ;
22692268 } else {
22702269 var sunif = args [ 1 ] . TextValue . Trim ( ) ;
2271- if ( sumifRegex . IsMatch ( sunif ) ) {
2272- count = MathVisitor . F_base_countif ( list , sunif ) ;
2273- sum = MathVisitor . F_base_sumif ( list , sunif , sumdbs ) ;
2270+ var m2 = sumifMatch ( sunif ) ;
2271+ if ( m2 != null ) {
2272+ count = F_base_countif ( list , m2 . Item1 , m2 . Item2 ) ;
2273+ sum = F_base_sumif ( list , m2 . Item1 , m2 . Item2 , sumdbs ) ;
22742274 } else {
22752275 return Operand . Error ( "Function AVERAGE parameter 2 error!" ) ;
22762276 }
@@ -2328,23 +2328,24 @@ public virtual Operand VisitCOUNT_fun(mathParser.COUNT_funContext context)
23282328 }
23292329 public virtual Operand VisitCOUNTIF_fun ( mathParser . COUNTIF_funContext context )
23302330 {
2331- var args = new List < Operand > ( ) ;
2332- foreach ( var item in context . expr ( ) ) { var aa = item . Accept ( this ) ; if ( aa . IsError ) { return aa ; } args . Add ( aa ) ; }
2331+ var exprs = context . expr ( ) ; var args = new List < Operand > ( exprs . Length ) ;
2332+ for ( int i = 0 ; i < exprs . Length ; i ++ ) { var aa = this . Visit ( exprs [ i ] ) ; if ( aa . IsError ) { return aa ; } args . Add ( aa ) ; }
23332333
23342334 List < decimal > list = new List < decimal > ( ) ;
23352335 var o = F_base_GetList ( args [ 0 ] , list ) ;
23362336 if ( o == false ) { return Operand . Error ( "Function COUNTIF parameter error!" ) ; }
23372337
23382338 int count ;
23392339 if ( args [ 1 ] . Type == OperandType . NUMBER ) {
2340- count = MathVisitor . F_base_countif ( list , args [ 1 ] . NumberValue ) ;
2340+ count = F_base_countif ( list , args [ 1 ] . NumberValue ) ;
23412341 } else {
23422342 if ( decimal . TryParse ( args [ 1 ] . TextValue . Trim ( ) , NumberStyles . Any , CultureInfo . InvariantCulture , out decimal d ) ) {
2343- count = MathVisitor . F_base_countif ( list , d ) ;
2343+ count = F_base_countif ( list , d ) ;
23442344 } else {
23452345 var sunif = args [ 1 ] . TextValue . Trim ( ) ;
2346- if ( sumifRegex . IsMatch ( sunif ) ) {
2347- count = MathVisitor . F_base_countif ( list , sunif ) ;
2346+ var m2 = sumifMatch ( sunif ) ;
2347+ if ( m2 != null ) {
2348+ count = F_base_countif ( list , m2 . Item1 , m2 . Item2 ) ;
23482349 } else {
23492350 return Operand . Error ( "Function COUNTIF parameter 2 error!" ) ;
23502351 }
@@ -2368,8 +2369,8 @@ public virtual Operand VisitSUM_fun(mathParser.SUM_funContext context)
23682369 }
23692370 public virtual Operand VisitSUMIF_fun ( mathParser . SUMIF_funContext context )
23702371 {
2371- var args = new List < Operand > ( ) ;
2372- foreach ( var item in context . expr ( ) ) { var aa = item . Accept ( this ) ; if ( aa . IsError ) { return aa ; } args . Add ( aa ) ; }
2372+ var exprs = context . expr ( ) ; var args = new List < Operand > ( exprs . Length ) ;
2373+ for ( int i = 0 ; i < exprs . Length ; i ++ ) { var aa = this . Visit ( exprs [ i ] ) ; if ( aa . IsError ) { return aa ; } args . Add ( aa ) ; }
23732374
23742375 List < decimal > list = new List < decimal > ( ) ;
23752376 var o = F_base_GetList ( args [ 0 ] , list ) ;
@@ -2386,14 +2387,15 @@ public virtual Operand VisitSUMIF_fun(mathParser.SUMIF_funContext context)
23862387
23872388 decimal sum ;
23882389 if ( args [ 1 ] . Type == OperandType . NUMBER ) {
2389- sum = MathVisitor . F_base_countif ( list , args [ 1 ] . NumberValue ) * args [ 1 ] . NumberValue ;
2390+ sum = F_base_countif ( list , args [ 1 ] . NumberValue ) * args [ 1 ] . NumberValue ;
23902391 } else {
2391- if ( decimal . TryParse ( args [ 1 ] . TextValue . Trim ( ) , NumberStyles . Any , CultureInfo . InvariantCulture , out _ ) ) {
2392- sum = MathVisitor . F_base_sumif ( list , '=' + args [ 1 ] . TextValue . Trim ( ) , sumdbs ) ;
2392+ if ( decimal . TryParse ( args [ 1 ] . TextValue . Trim ( ) , NumberStyles . Any , CultureInfo . InvariantCulture , out decimal d ) ) {
2393+ sum = F_base_sumif ( list , d , sumdbs ) ;
23932394 } else {
23942395 var sunif = args [ 1 ] . TextValue . Trim ( ) ;
2395- if ( sumifRegex . IsMatch ( sunif ) ) {
2396- sum = MathVisitor . F_base_sumif ( list , sunif , sumdbs ) ;
2396+ var m2 = sumifMatch ( sunif ) ;
2397+ if ( m2 != null ) {
2398+ sum = F_base_sumif ( list , m2 . Item1 , m2 . Item2 , sumdbs ) ;
23972399 } else {
23982400 return Operand . Error ( "Function SUMIF parameter 2 error!" ) ;
23992401 }
@@ -2809,44 +2811,95 @@ public virtual Operand VisitWEIBULL_fun(mathParser.WEIBULL_funContext context)
28092811 return Operand . Create ( ExcelFunctions . WEIBULL ( ( double ) x , ( double ) shape , ( double ) scale , state ) ) ;
28102812 }
28112813
2814+ private static Tuple < string , decimal > sumifMatch ( string s )
2815+ {
2816+ var c = s [ 0 ] ;
2817+ if ( c == '>' || c == '>' ) {
2818+ if ( s . Length > 1 && ( s [ 1 ] == '=' || s [ 1 ] == '=' ) ) {
2819+ if ( decimal . TryParse ( s . AsSpan ( 2 ) . Trim ( ) , out decimal d ) ) {
2820+ return Tuple . Create ( ">=" , d ) ;
2821+ }
2822+ } else if ( decimal . TryParse ( s . AsSpan ( 1 ) . Trim ( ) , out decimal d ) ) {
2823+ return Tuple . Create ( ">" , d ) ;
2824+ }
2825+ } else if ( c == '<' || c < '<' ) {
2826+ if ( s . Length > 1 && ( s [ 1 ] == '=' || s [ 1 ] == '=' ) ) {
2827+ if ( decimal . TryParse ( s . AsSpan ( 2 ) . Trim ( ) , out decimal d ) ) {
2828+ return Tuple . Create ( "<=" , d ) ;
2829+ }
2830+ } else if ( s . Length > 1 && ( s [ 1 ] == '>' || s [ 1 ] == '>' ) ) {
2831+ if ( decimal . TryParse ( s . AsSpan ( 2 ) . Trim ( ) , out decimal d ) ) {
2832+ return Tuple . Create ( "!=" , d ) ;
2833+ }
2834+ } else if ( decimal . TryParse ( s . AsSpan ( 1 ) . Trim ( ) , out decimal d ) ) {
2835+ return Tuple . Create ( "<" , d ) ;
2836+ }
2837+ } else if ( c == '=' || c == '=' ) {
2838+ var index = 1 ;
2839+ if ( s . Length > 1 && ( s [ 1 ] == '=' || s [ 1 ] == '=' ) ) {
2840+ index = 2 ;
2841+ if ( s . Length > 2 && ( s [ 2 ] == '=' || s [ 2 ] == '=' ) ) {
2842+ index = 3 ;
2843+ }
2844+ }
2845+ if ( decimal . TryParse ( s . AsSpan ( index ) . Trim ( ) , out decimal d ) ) {
2846+ return Tuple . Create ( "=" , d ) ;
2847+ }
2848+ } else if ( c == '!' || c == '!' ) {
2849+ var index = 1 ;
2850+ if ( s . Length > 1 && ( s [ 1 ] == '=' || s [ 1 ] == '=' ) ) {
2851+ index = 2 ;
2852+ if ( s . Length > 2 && ( s [ 2 ] == '=' || s [ 2 ] == '=' ) ) {
2853+ index = 3 ;
2854+ }
2855+ }
2856+ if ( decimal . TryParse ( s . AsSpan ( index ) . Trim ( ) , out decimal d ) ) {
2857+ return Tuple . Create ( "!=" , d ) ;
2858+ }
2859+ }
2860+ return null ;
2861+ }
28122862 private static int F_base_countif ( List < decimal > dbs , decimal d )
28132863 {
28142864 int count = 0 ;
2815- //d = Math.Round(d, 12, MidpointRounding.AwayFromZero);
2816- foreach ( var item in dbs ) {
2865+ for ( int i = 0 ; i < dbs . Count ; i ++ ) {
2866+ var item = dbs [ i ] ;
28172867 if ( item == d ) {
28182868 count ++ ;
28192869 }
2820- //if (Math.Round(item, 12, MidpointRounding.AwayFromZero) == d) {
2821- // count++;
2822- //}
28232870 }
28242871 return count ;
28252872 }
2826- private static int F_base_countif ( List < decimal > dbs , string s )
2873+ private static int F_base_countif ( List < decimal > dbs , string s , decimal d )
28272874 {
2828- var m = sumifRegex . Match ( s ) ;
2829- var d = decimal . Parse ( m . Groups [ 2 ] . Value , NumberStyles . Any , CultureInfo . InvariantCulture ) ;
2830- var ss = m . Groups [ 1 ] . Value ;
28312875 int count = 0 ;
2832-
2833- foreach ( var item in dbs ) {
2834- if ( MathVisitor . F_base_compare ( item , d , ss ) ) {
2876+ for ( int i = 0 ; i < dbs . Count ; i ++ ) {
2877+ var item = dbs [ i ] ;
2878+ if ( F_base_compare ( item , d , s ) ) {
28352879 count ++ ;
28362880 }
28372881 }
28382882 return count ;
28392883 }
2840-
2841- private static decimal F_base_sumif ( List < decimal > dbs , string s , List < decimal > sumdbs )
2884+ private static decimal F_base_sumif ( List < decimal > dbs , decimal d , List < decimal > sumdbs )
28422885 {
2843- var m = sumifRegex . Match ( s ) ;
2844- var d = decimal . Parse ( m . Groups [ 2 ] . Value , NumberStyles . Any , CultureInfo . InvariantCulture ) ;
2845- var ss = m . Groups [ 1 ] . Value ;
28462886 decimal sum = 0 ;
2847-
28482887 for ( int i = 0 ; i < dbs . Count ; i ++ ) {
2849- if ( MathVisitor . F_base_compare ( dbs [ i ] , d , ss ) ) {
2888+ var item = dbs [ i ] ;
2889+ if ( item == d ) {
2890+ sum += sumdbs [ i ] ;
2891+ }
2892+ //if (Math.Round(item, 10, MidpointRounding.AwayFromZero) == d) {
2893+ // sum += item;
2894+ //}
2895+ }
2896+ return sum ;
2897+ }
2898+ private static decimal F_base_sumif ( List < decimal > dbs , string s , decimal d , List < decimal > sumdbs )
2899+ {
2900+ decimal sum = 0 ;
2901+ for ( int i = 0 ; i < dbs . Count ; i ++ ) {
2902+ if ( F_base_compare ( dbs [ i ] , d , s ) ) {
28502903 sum += sumdbs [ i ] ;
28512904 }
28522905 }
@@ -2873,8 +2926,7 @@ private static bool F_base_compare(decimal a, decimal b, string ss)
28732926 return a != b ;
28742927 //return Math.Round(a - b, 12, MidpointRounding.AwayFromZero) != 0;
28752928 }
2876-
2877- private bool F_base_GetList ( List < Operand > args , List < decimal > list )
2929+ private static bool F_base_GetList ( List < Operand > args , List < decimal > list )
28782930 {
28792931 foreach ( var item in args ) {
28802932 if ( item . Type == OperandType . NUMBER ) {
@@ -2895,7 +2947,7 @@ private bool F_base_GetList(List<Operand> args, List<decimal> list)
28952947 }
28962948 return true ;
28972949 }
2898- private bool F_base_GetList ( Operand args , List < decimal > list )
2950+ private static bool F_base_GetList ( Operand args , List < decimal > list )
28992951 {
29002952 if ( args . IsError ) { return false ; }
29012953 if ( args . Type == OperandType . NUMBER ) {
@@ -2915,8 +2967,7 @@ private bool F_base_GetList(Operand args, List<decimal> list)
29152967 }
29162968 return true ;
29172969 }
2918-
2919- private bool F_base_GetList ( Operand args , List < string > list )
2970+ private static bool F_base_GetList ( Operand args , List < string > list )
29202971 {
29212972 if ( args . IsError ) { return false ; }
29222973 if ( args . Type == OperandType . ARRARY ) {
@@ -2934,9 +2985,7 @@ private bool F_base_GetList(Operand args, List<string> list)
29342985 }
29352986 return true ;
29362987 }
2937-
2938-
2939- private bool F_base_GetList ( List < Operand > args , List < string > list )
2988+ private static bool F_base_GetList ( List < Operand > args , List < string > list )
29402989 {
29412990 foreach ( var item in args ) {
29422991 if ( item . Type == OperandType . ARRARY ) {
0 commit comments