¿Cómo puedo comprobar si el contenido de una variable es numérico? - página 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);
  }  
//+------------------------------------------------------------------+
Gracias por tus códigos de ejemplo. Pero su palabra clave "IsNumeric" no parece pertenecer a MQL4. Por favor, corrígeme si me equivoco. Sin embargo, su código se ejecuta muy bien y esto es un ejemplo perfecto para lo que he estado buscando. Gracias.
 
macpee Pero su palabra clave "IsNumeric" no parece pertenecer a MQL4. Por favor, corrígeme si me equivoco.
No es una palabra clave, es una función que proporcionó arriba.
 
whroeder1:
No es una palabra clave, es una función que proporcionó arriba.
Oh, mírame. Debería haberlo sabido. Gracias @whroeder1.
 
macpee:
Oh, mírame. Debería haberlo sabido. Gracias @whroeder1.
Por supuesto que un punto (.) debería ser numérico ya que (.) se considera lo mismo con un punto y cero (.0) que de hecho es cero (0). Ahora he probado a aumentar el número de punto (.....) y sigue reconociéndolo como numérico. Necesitamos el código del punto (.) para eliminar el punto adicional (....) una vez citado el primer punto en
if((char1>47 && char1<58) || char1==46)
Por cierto, no encuentro la lista del código (ASCII, supongo).

Otra cosa es cómo introducir números negativos. El código necesita capturar el signo de negación (-) sólo al principio de la entrada.

Además, para perfeccionar el código. Necesita aceptar el símbolo de negación (-) incluso en medio de números como (45-20) y tratarlo como una sustracción y evaluar y luego usar el código
int char1=StringGetChar(text,i);
para comprobar que el resultado es numérico. Podemos hacer esto para las cuatro operaciones binarias básicas. Pero eso no es importante para nosotros ahora.

La idea es hacer que la propiedad OBJPROP_TEXT de OBT_EDIT acepte los datos del calendario económico y los trate como los números que son. Por eso es muy importante una función incorporada de IsNumeric para evitar escribir un código innecesariamente grande para ello.
 
macpee:
Por supuesto, un punto (.) debería ser numérico, ya que (.) se considera lo mismo con un punto y cero (.0), que de hecho es cero (0). Ahora he probado a aumentar el número de punto (.....) y sigue reconociéndolo como numérico. Necesitamos el código del punto (.) para eliminar el punto adicional (....) una vez citado el primer punto en
if((char1>47 && char1<58) || char1==46)
Por cierto, no encuentro la lista del código (ASCII, supongo).

Otra cosa es cómo introducir números negativos. El código necesita capturar el signo de negación (-) sólo al principio de la entrada.

Además, para perfeccionar el código. Necesita aceptar el símbolo de negación (-) incluso en medio de números como (45-20) y tratarlo como una sustracción y evaluar y luego usar el código
int char1=StringGetChar(text,i);
para comprobar que el resultado es numérico. Podemos hacer esto para las cuatro operaciones binarias básicas. Pero eso no es importante para nosotros ahora.

La idea es hacer que la propiedad OBJPROP_TEXT de OBT_EDIT acepte los datos del calendario económico y los trate como los números que son. Por eso una función incorporada de IsNumeric es bastante importante para evitar escribir un código innecesariamente grande para ello.
O quizás una solución es convertir la cadena a doble después de la comprobación IsNumeric.
 

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

Otra cosa es cómo introducir números negativos. El código necesita capturar el signo de negación (-) sólo al principio de la entrada.

¿Hay un eco aquí?

honest_knave:

Sí, ese tipo de cosas.

Tendrías que tener cuidado con:

  • Múltiples puntos decimales (pasaría pero no debería)
  • El uso de los símbolos + y - (no pasaría pero debería)
  • El uso de , como separador de miles o como punto decimal (no se aprobaría pero debería)
  • Un solo punto decimal sin otros caracteres (se aprobaría pero no debería)
  • Números que superan la capacidad del molde
  • Espacios

________________________________

macpee:

Por cierto, no encuentro la lista del código (ASCII, supongo).

Vamos, inténtalo. Sé que estás deseando tener la oportunidad de perfeccionar tus habilidades de búsqueda.

________________________________

macpee:

La idea es hacer que la propiedad OBJPROP_TEXT de OBT_EDIT acepte los datos del calendario económico y los trate como los números que son. Por eso una función incorporada de IsNumeric es bastante importante para evitar escribir un código innecesariamente grande para ello.

Aunque puede que haya entendido mal tu intención, si quieres que el usuario introduzca fechas en un cuadro de edición y luego las interprete como fechas-tiempo (posiblemente no si te interesan los números negativos), no estoy convencido de que este sea el mejor enfoque por varias razones.

 
honest_knave:

¿Hay eco aquí?

________________________________

Vamos, inténtalo. Sé que estás deseando tener la oportunidad de perfeccionar tus habilidades de búsqueda.

________________________________

Aunque puede que haya entendido mal tu intención, si quieres que el usuario introduzca fechas en un cuadro de texto y luego las interprete como fechas-tiempo (posiblemente no si te interesan los números negativos), no estoy convencido de que este sea el mejor enfoque por varias razones.

En realidad, los datos económicos en cuestión no incluyen fechas, sólo datos "reales", "previstos", "anteriores" y posiblemente "revisados". Por supuesto, tampoco tenemos la intención de introducir símbolos como B (de mil millones), % (de porcentaje), etc. Sólo números reales puros sin espacios. La idea es calcular lo que yo llamo "Índice de liberación simultánea". Se trata de combinar un conjunto de datos económicos publicados simultáneamente y verlos como un solo dato. Combinaría todos los "reales" como un "real", todos los "pronósticos" como un "pronóstico", etc, para ver la relación entre el "real" combinado y el "pronóstico" combinado, etc.

 
macpee:
if((char1>47 && char1<58) || char1==46)
Por cierto, no encuentro la lista del código (ASCII, supongo).
No codifiques los números con fuerza. Haz que tu código sea auto-documentado.
if((char1>='0' && char1<='9') || char1=='.')
Constantes de carácter - Tipos de enteros - Tipos de datos - Fundamentos del lenguaje - Referencia MQL4
 
macpee:
En realidad, los datos económicos en cuestión no incluyen fechas, sólo datos "reales", "previstos", "anteriores" y posiblemente "revisados". Por supuesto, tampoco tenemos la intención de introducir símbolos como B (de mil millones), % (de porcentaje), etc. Sólo números reales puros sin espacios. La idea es calcular lo que yo llamo "Índice de liberación simultánea". Se trata de combinar un conjunto de datos económicos publicados simultáneamente y verlos como un solo dato. Combinaría todos los "reales" como un "real", todos los "pronósticos" como un "pronóstico", etc, para ver la relación entre el "real" combinado y el "pronóstico" combinado, etc.

Entonces:

  • Pasar la cadena por referencia
  • Quitar los espacios en blanco
  • Elimina los ','
  • Compruebe que "+" o "-" sólo aparecen como primer carácter
  • Compruebe que todos los demás caracteres sean números entre 0 y 9

Por ejemplo

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);
  }

Si el resultado es verdadero, puede convertir la cadena en un número.

 
honest_knave:

Entonces:

  • Pasar la cadena por referencia
  • Quitar los espacios en blanco
  • Elimina los ','
  • Compruebe que sólo hay un '.'
  • Compruebe que "+" o "-" sólo aparecen como primer carácter
  • Compruebe que todos los demás caracteres sean números entre 0 y 9

Por ejemplo

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);
  }

Si devuelve true, puede convertir la cadena en un número.

Te gusta mucho la complicación . Si el objetivo es sólo procesar números reales, utilice StringToDouble() y un procesamiento del caso especial 0.