How do I check if the content of a variable is numeric? - page 3

 
Ernst Van Der Merwe:
void OnStart()
  {
//---
   ObjectCreate("SimultaneousReleaseIndex1",OBJ_LABEL,0,0,0);
   ObjectSetString(0,"SimultaneousReleaseIndex1",OBJPROP_TEXT,"Four");
   ObjectCreate("SimultaneousReleaseIndex2",OBJ_LABEL,0,0,0);
   ObjectSetString(0,"SimultaneousReleaseIndex2",OBJPROP_TEXT,"44");
   ObjectCreate("SimultaneousReleaseIndex3",OBJ_LABEL,0,0,0);
   ObjectSetString(0,"SimultaneousReleaseIndex3",OBJPROP_TEXT,"Forty4");
   ObjectCreate("SimultaneousReleaseIndex4",OBJ_LABEL,0,0,0);
   ObjectSetString(0,"SimultaneousReleaseIndex4",OBJPROP_TEXT,".1234567890");
  
   if(IsNumeric(ObjectGetString(0,"SimultaneousReleaseIndex1",OBJPROP_TEXT)))
      Print("text1 is numeric");
   if(IsNumeric(ObjectGetString(0,"SimultaneousReleaseIndex2",OBJPROP_TEXT)))
      Print("text2 is numeric");
   if(IsNumeric(ObjectGetString(0,"SimultaneousReleaseIndex3",OBJPROP_TEXT)))
      Print("text3 is numeric");
   if(IsNumeric(ObjectGetString(0,"SimultaneousReleaseIndex4",OBJPROP_TEXT)))
      Print("text4 is numeric");
  }
//---
bool IsNumeric(string text)
  {
   int length=StringLen(text);
   for(int i=0;i<length;i++)
     {
      int char1=StringGetChar(text,i);
      if((char1>47 && char1<58) || char1==46)
         continue;
      else
         return(false);
     }
   return(true);
  }  
//+------------------------------------------------------------------+
Thank you for your example codes. But your "IsNumeric" keyword does not seem to belong to MQL4. Please correct me if I am wrong. Yet your code is running very fine and this is a perfect example to what I have been seeking. Thank you.
 
macpee But your "IsNumeric" keyword does not seem to belong to MQL4. Please correct me if I am wrong.
Not a keyword, it's a function that he provided above.
 
whroeder1:
Not a keyword, it's a function that he provided above.
Oh, look at me. I should have known. Thank you @whroeder1.
 
macpee:
Oh, look at me. I should have known. Thank you @whroeder1.
Of course a period (.) should be numeric since (.) is regarded as the same thing with a period and zero (.0) which is in fact zero (0). Now I tried increasing the number of period (.....) and it is still recognizing it as numeric. We need the code for period (.) so as to eliminate additional period (....) once the first period has been cited in
if((char1>47 && char1<58) || char1==46)
By the way, I cannot find the list of the code (ASCII, I presume).

Another thing is how to enter negative numbers. The code needs to capture the negation sign (-) only at the beginning of the entry.

Moreover, in order to perfect the code. It needs to accept the negation symbol (-) even in the middle of numbers such as (45-20) and treat it as subtraction and evaluate and then use the code
int char1=StringGetChar(text,i);
to check that the result is Numeric. We can do this for all four basic binary operations. But that is not important to us now.

The whole idea is to make OBJPROP_TEXT property of OBT_EDIT to accept economic calendar data and treat them as the numbers that they are. That is why an inbuilt function of IsNumeric is quite important to avoid writing unnecessarily large code for it.
 
macpee:
Of course a period (.) should be numeric since (.) is regarded as the same thing with a period and zero (.0) which is in fact zero (0). Now I tried increasing the number of period (.....) and it is still recognizing it as numeric. We need the code for period (.) so as to eliminate additional period (....) once the first period has been cited in
if((char1>47 && char1<58) || char1==46)
By the way, I cannot find the list of the code (ASCII, I presume).

Another thing is how to enter negative numbers. The code needs to capture the negation sign (-) only at the beginning of the entry.

Moreover, in order to perfect the code. It needs to accept the negation symbol (-) even in the middle of numbers such as (45-20) and treat it as subtraction and evaluate and then use the code
int char1=StringGetChar(text,i);
to check that the result is Numeric. We can do this for all four basic binary operations. But that is not important to us now.

The whole idea is to make OBJPROP_TEXT property of OBT_EDIT to accept economic calendar data and treat them as the numbers that they are. That is why an inbuilt function of IsNumeric is quite important to avoid writing unnecessarily large code for it.
Or maybe a solution is to convert the string to double after the IsNumeric check.
 

macpee:
Of course a period (.) should be numeric since (.) is regarded as the same thing with a period and zero (.0) which is in fact zero (0). Now I tried increasing the number of period (.....) and it is still recognizing it as numeric. We need the code for period (.) so as to eliminate additional period (....) once the first period has been cited in

Another thing is how to enter negative numbers. The code needs to capture the negation sign (-) only at the beginning of the entry. 

Is there an echo in here? 

honest_knave:

Yep, that sort of thing.

You'd need to be careful about:

  • Multiple decimal points (would pass but shouldn't)
  • Use of + and - symbols (wouldn't pass but should)
  • Use of , as either a thousands separator, or as a decimal point (wouldn't pass but should)
  • A solitary decimal point with no other characters (would pass but shouldn't) 
  • Numbers beyond the capacity of the cast
  • Spaces

 ________________________________

macpee:

By the way, I cannot find the list of the code (ASCII, I presume).

Go on, give it a go. I know you've been itching for a chance to hone your search skills.

 ________________________________

macpee:

The whole idea is to make OBJPROP_TEXT property of OBT_EDIT to accept economic calendar data and treat them as the numbers that they are. That is why an inbuilt function of IsNumeric is quite important to avoid writing unnecessarily large code for it.

 While I may have misunderstood your intention, if you want the user to enter dates into an edit box and then interpret them as datetimes (possibly not if you are interested in negative numbers), I'm not convinced this is the best approach for a number of reasons.

 
honest_knave:

Is there an echo in here? 

 ________________________________

Go on, give it a go. I know you've been itching for a chance to hone your search skills.

 ________________________________

 While I may have misunderstood your intention, if you want the user to enter dates into a text box and then interpret them as datetimes (possibly not if you are interested in negative numbers), I'm not convinced this is the best approach for a number of reasons.

Actually the economic data in question do not include dates - just 'actual', 'forecast', 'previous' and possibly 'revised' data. Of course we also do not intend to enter symbols such as B(for billion), %(for percent) etc. Just pure real numbers without spaces. The idea is to calculate what I call "Simultaneous Release Index". It is meant to combine a set of economic data released simultaneously and see them as one datum. I would combine all 'actuals' as one 'actual', all 'forecasts' as one 'forecast', etc, in order to see the relationship between the combined 'actual' and combined 'forecast' etc.

 
macpee:
if((char1>47 && char1<58) || char1==46)
By the way, I cannot find the list of the code (ASCII, I presume).
Don't hard code numbers. Make your code self-documenting.
if((char1>='0' && char1<='9') || char1=='.')
Character Constants - Integer Types - Data Types - Language Basics - MQL4 Reference
 
macpee:
Actually the economic data in question do not include dates - just 'actual', 'forecast', 'previous' and possibly 'revised' data. Of course we also do not intend to enter symbols such as B(for billion), %(for percent) etc. Just pure real numbers without spaces. The idea is to calculate what I call "Simultaneous Release Index". It is meant to combine a set of economic data released simultaneously and see them as one datum. I would combine all 'actuals' as one 'actual', all 'forecasts' as one 'forecast', etc, in order to see the relationship between the combined 'actual' and combined 'forecast' etc.

So:

  • Pass the string by reference
  • Strip out the blank spaces
  • Strip out the ','
  • Check there is only one '.'
  • Check that '+' or '-' only appear as the first character
  • Check that every other character is a number between 0 and 9

e.g.

bool IsValidNumber(string &text)
  {
   StringReplace(text," ",NULL);
   StringReplace(text,",",NULL);
   int point_cnt = 0;
   for(int i=StringLen(text)-1; i>=0; i--)
     {
      int this_char = StringGetChar(text,i);
      if(this_char == '.')
        {
         point_cnt++;
         if(point_cnt>1)       return(false);
         if(StringLen(text)<2) return(false);
        }
      else if(this_char == '+' || this_char == '-')
        {
         if(i>0) return(false);
        }
      else if(this_char < '0' || this_char > '9') return(false);
     }
   return(true);
  }

 

 If it returns true, you can cast the string as a number.

 
honest_knave:

So:

  • Pass the string by reference
  • Strip out the blank spaces
  • Strip out the ','
  • Check there is only one '.'
  • Check that '+' or '-' only appear as the first character
  • Check that every other character is a number between 0 and 9

e.g.

bool IsValidNumber(string &text)
  {
   StringReplace(text," ",NULL);
   StringReplace(text,",",NULL);
   int point_cnt = 0;
   for(int i=StringLen(text)-1; i>=0; i--)
     {
      int this_char = StringGetChar(text,i);
      if(this_char == '.')
        {
         point_cnt++;
         if(point_cnt>1)       return(false);
         if(StringLen(text)<2) return(false);
        }
      else if(this_char == '+' || this_char == '-')
        {
         if(i>0) return(false);
        }
      else if(this_char < '0' || this_char > '9') return(false);
     }
   return(true);
  }

 

 If it returns true, you can cast the string as a number.

You really like complication . If the goal is just to process real numbers, use StringToDouble() and a processing of special case 0.
Reason: