Come controllo se il contenuto di una variabile è numerico? - pagina 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);
  }  
//+------------------------------------------------------------------+
Grazie per i vostri codici di esempio. Ma la tua parola chiave "IsNumeric" non sembra appartenere a MQL4. Per favore correggetemi se mi sbaglio. Eppure il tuo codice funziona molto bene e questo è un esempio perfetto per quello che stavo cercando. Grazie.
 
macpee Ma la sua parola chiave "IsNumeric" non sembra appartenere a MQL4. Per favore correggetemi se mi sbaglio.
Non è una parola chiave, è una funzione che ha fornito sopra.
 
whroeder1:
Non è una parola chiave, è una funzione che ha fornito sopra.
Oh, guardatemi. Avrei dovuto saperlo. Grazie @whroeder1.
 
macpee:
Oh, guardami. Avrei dovuto saperlo. Grazie @whroeder1.
Naturalmente un periodo (.) dovrebbe essere numerico poiché (.) è considerato la stessa cosa con un periodo e lo zero (.0) che è in effetti zero (0). Ora ho provato ad aumentare il numero di periodo (.....) e lo riconosce ancora come numerico. Abbiamo bisogno del codice per il periodo (.) in modo da eliminare il periodo aggiuntivo (....) una volta che il primo periodo è stato citato in
if((char1>47 && char1<58) || char1==46)
A proposito, non riesco a trovare la lista del codice (ASCII, presumo).

Un'altra cosa è come inserire numeri negativi. Il codice deve catturare il segno di negazione (-) solo all'inizio dell'inserimento.

Inoltre, per perfezionare il codice. Deve accettare il simbolo di negazione (-) anche in mezzo ai numeri come (45-20) e trattarlo come una sottrazione e valutare e poi usare il codice
int char1=StringGetChar(text,i);
per controllare che il risultato sia Numeric. Possiamo fare questo per tutte e quattro le operazioni binarie di base. Ma questo non è importante per noi ora.

L'intera idea è di fare in modo che la proprietà OBJPROP_TEXT di OBT_EDIT accetti i dati del calendario economico e li tratti come i numeri che sono. Ecco perché una funzione integrata di IsNumeric è abbastanza importante per evitare di scrivere codice inutilmente grande per essa.
 
macpee:
Naturalmente un periodo (.) dovrebbe essere numerico poiché (.) è considerato la stessa cosa di un periodo e dello zero (.0) che è in effetti zero (0). Ora ho provato ad aumentare il numero di periodo (.....) e lo riconosce ancora come numerico. Abbiamo bisogno del codice per il periodo (.) in modo da eliminare il periodo aggiuntivo (....) una volta che il primo periodo è stato citato in
if((char1>47 && char1<58) || char1==46)
A proposito, non riesco a trovare la lista del codice (ASCII, presumo).

Un'altra cosa è come inserire numeri negativi. Il codice deve catturare il segno di negazione (-) solo all'inizio dell'inserimento.

Inoltre, per perfezionare il codice. Deve accettare il simbolo di negazione (-) anche in mezzo ai numeri come (45-20) e trattarlo come una sottrazione e valutare e poi usare il codice
int char1=StringGetChar(text,i);
per controllare che il risultato sia Numeric. Possiamo fare questo per tutte e quattro le operazioni binarie di base. Ma questo non è importante per noi ora.

L'intera idea è di fare in modo che la proprietà OBJPROP_TEXT di OBT_EDIT accetti i dati del calendario economico e li tratti come i numeri che sono. Ecco perché una funzione integrata di IsNumeric è abbastanza importante per evitare di scrivere codice inutilmente grande per essa.
O forse una soluzione è convertire la stringa in doppio dopo il controllo 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

Un'altra cosa è come inserire numeri negativi. Il codice deve catturare il segno di negazione (-) solo all'inizio dell'inserimento.

C'è un'eco qui?

honest_knave:

Sì, questo genere di cose.

Dovresti stare attento a:

  • Punti decimali multipli (passerebbe ma non dovrebbe)
  • Uso dei simboli + e - (non passerebbe ma dovrebbe)
  • Uso di , come separatore delle migliaia o come punto decimale (non passerebbe ma dovrebbe)
  • Un solo punto decimale senza altri caratteri (passerebbe ma non dovrebbe)
  • Numeri oltre la capacità del calco
  • Spazi

________________________________

macpee:

A proposito, non riesco a trovare l'elenco del codice (ASCII, presumo).

Avanti, provaci. So che non vedi l'ora di affinare le tue capacità di ricerca.

________________________________

macpee:

L'intera idea è di fare in modo che la proprietà OBJPROP_TEXT di OBT_EDIT accetti i dati del calendario economico e li tratti come i numeri che sono. Ecco perché una funzione integrata di IsNumeric è abbastanza importante per evitare di scrivere codice inutilmente grande per essa.

Anche se potrei aver frainteso la tua intenzione, se vuoi che l'utente inserisca le date in una casella di modifica e poi le interpreti come datetime (possibilmente non se sei interessato ai numeri negativi), non sono convinto che questo sia l'approccio migliore per una serie di motivi.

 
honest_knave:

C'è un'eco qui dentro?

________________________________

Avanti, fai un tentativo. So che non vedi l'ora di affinare le tue capacità di ricerca.

________________________________

Anche se potrei aver frainteso la tua intenzione, se vuoi che l'utente inserisca le date in una casella di testo e poi le interpreti come datetime (possibilmente non se sei interessato ai numeri negativi), non sono convinto che questo sia l'approccio migliore per una serie di motivi.

In realtà i dati economici in questione non includono date - solo dati "effettivi", "previsti", "precedenti" ed eventualmente "rivisti". Naturalmente non intendiamo nemmeno inserire simboli come B(per miliardi), %(per percentuale) ecc. Solo puri numeri reali senza spazi. L'idea è di calcolare quello che io chiamo "Simultaneous Release Index". Ha lo scopo di combinare una serie di dati economici rilasciati simultaneamente e vederli come un unico dato. Combinerei tutti gli "effettivi" come un "effettivo", tutte le "previsioni" come una "previsione", ecc, al fine di vedere la relazione tra l'"effettivo" combinato e la "previsione" combinata, ecc.

 
macpee:
if((char1>47 && char1<58) || char1==46)
A proposito, non riesco a trovare la lista del codice (ASCII, presumo).
Non fate numeri hard code. Rendi il tuo codice auto-documentante.
if((char1>='0' && char1<='9') || char1=='.')
Costanti di caratteri - Tipi di interi - Tipi di dati - Fondamenti del linguaggio - Riferimento MQL4
 
macpee:
In realtà i dati economici in questione non includono date - solo dati 'effettivi', 'previsti', 'precedenti' e possibilmente 'rivisti'. Naturalmente non intendiamo nemmeno inserire simboli come B(per miliardi), %(per percentuale) ecc. Solo puri numeri reali senza spazi. L'idea è di calcolare quello che io chiamo "Simultaneous Release Index". Ha lo scopo di combinare una serie di dati economici rilasciati simultaneamente e vederli come un unico dato. Combinerei tutti gli "effettivi" come un "effettivo", tutte le "previsioni" come una "previsione", ecc, al fine di vedere la relazione tra l'"effettivo" combinato e la "previsione" combinata, ecc.

Quindi:

  • Passare la stringa per riferimento
  • Elimina gli spazi vuoti
  • Elimina i ','.
  • Controlla che '+' o '-' appaiano solo come primo carattere
  • Controlla che ogni altro carattere sia un numero tra 0 e 9

es.

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

Se restituisce true, puoi lanciare la stringa come un numero.

 
honest_knave:

Quindi:

  • Passare la stringa per riferimento
  • Elimina gli spazi vuoti
  • Elimina i ','.
  • Controlla che ci sia un solo '.
  • Controlla che '+' o '-' appaiano solo come primo carattere
  • Controlla che ogni altro carattere sia un numero tra 0 e 9

es.

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

Se restituisce true, puoi lanciare la stringa come un numero.

Vi piace molto la complicazione . Se l'obiettivo è solo quello di elaborare numeri reali, usate StringToDouble() e un'elaborazione del caso speciale 0.