De números a cadenas y viceversa

La conversión de números a cadenas y viceversa, de cadenas a números, puede realizarse mediante el operador conversión explícita de tipos. Por ejemplo, para los tipos double y string, podría tener este aspecto:

double number = (double)text;
string text = (string)number;

Las cadenas pueden convertirse a otros tipos numéricos, como float, long, int, etc.

Observe que la conversión a un tipo real (float) proporciona menos dígitos significativos, lo que en algunas aplicaciones puede considerarse una ventaja, ya que proporciona una representación más compacta y fácil de leer.

En términos estrictos, esta conversión de tipos no es obligatoria, ya que, aunque no exista ningún operador de conversión explícito, el compilador producirá la conversión de tipos de forma implícita. No obstante, en este caso recibirá una advertencia del compilador, por lo que se recomienda hacer siempre explícitas las conversiones de tipos.

La API de MQL5 proporciona algunas otras funciones útiles, que se describen a continuación. Las descripciones van seguidas de un ejemplo general.

double StringToDouble(string text)

La función StringToDouble convierte una cadena en un número double.

Esto es completamente análogo a la conversión de tipos a (double). En realidad, su finalidad práctica se limita a preservar la compatibilidad con los códigos fuente heredados. El método preferido es la conversión de tipos, ya que es más compacta y se implementa dentro de la sintaxis del lenguaje.

Según el proceso de conversión, una cadena debe contener una secuencia de caracteres que cumplan las reglas de escritura de literales de tipo numérico (tanto float como integer). En particular, una cadena puede comenzar con un signo '+' o '-' , seguido de un dígito, y puede continuar como una secuencia de dígitos.

Los números reales pueden contener un único carácter de punto '.' que separa la parte fraccionaria y un exponente opcional con el siguiente formato: carácter 'e' o 'E' seguido de una secuencia de dígitos para el grado (también puede ir precedido de un '+' o '-').

Para los números enteros se admite la notación hexadecimal, es decir, el prefijo «0x» puede ir seguido no sólo de dígitos decimales, sino también de 'A', 'B', 'C', 'D', 'E', 'F' (en cualquier posición).

Cuando se encuentra en la cadena cualquier carácter no esperado (como una letra, un signo de puntuación, un segundo punto o un espacio intermedio), la conversión finaliza. En este caso, si había caracteres permitidos antes de esta posición, se interpretan como un número, y si no, el resultado será 0.

Los caracteres vacíos iniciales (espacios, tabuladores, nuevas líneas) se omiten y no afectan a la conversión. Si van seguidos de números y otros caracteres que cumplan las normas, el número se recibirá correctamente.

En la siguiente tabla se ofrecen algunos ejemplos de conversiones válidas con explicaciones.

cadena

double

Resultado

"123.45"

123.45

Un punto decimal

"\t 123"

123.0

Los espacios en blanco al principio no se tienen en cuenta.

"-12345"

-12345.0

Un número con signo

"123e-5"

0.00123

Notación científica con exponente

"0x12345"

74565.0

Notación hexadecimal

En la siguiente tabla se muestran ejemplos de conversiones incorrectas.

cadena

double

Resultado

"x12345"

0.0

Empieza por un carácter no resuelto (letra)

"123x45"

123.0

La letra después de 123 rompe la conversión

" 12 3"

12.0

El espacio después de 12 rompe la conversión

"123.4.5"

123.4

El segundo punto decimal después de 123.4 rompe la conversión

"1,234.50"

1.0

La coma después de 1 rompe la conversión

"-+12345"

0.0

Demasiados signos (dos)

string DoubleToString(double number, int digits = 8)

La función DoubleToString convierte un número en una cadena con la precisión especificada (número de dígitos de -16 a 16).

Realiza un trabajo similar al de convertir un número a (string) pero permite elegir, mediante el segundo parámetro, la precisión numérica de la cadena resultante.

El operador (string) aplicado a double muestra 16 dígitos significativos (total, incluyendo mantisa y parte fraccionaria). El equivalente completo de esto no puede conseguirse con una función.

Si el parámetro digits es mayor o igual que 0, indica el número de decimales. En este caso, el número de caracteres antes de la marca decimal viene determinado por el propio número (lo grande que es), y si el número total de caracteres en la mantisa y el indicado en digits resulta ser mayor que 16, entonces los dígitos menos significativos contendrán «basura» (debido a cómo se almacenan los números reales). 16 caracteres representan la precisión media máxima para el tipo double, es decir, si se establece digits en 16 (máximo), sólo se obtendrá una representación precisa de los valores inferiores a 10.

Si el parámetro digits es menor que 0, especifica el número de dígitos significativos, y este número se mostrará en formato científico con un exponente. En términos de precisión (pero no de formato de grabación), la configuración de digits=-16 en la función genera un resultado cercano a la conversión (string).

La función, por regla general, se utiliza para dar un formato uniforme a los conjuntos de datos (incluida la alineación a la derecha de una columna de una tabla determinada), en los que los valores tienen la misma precisión decimal (por ejemplo, el número de decimales del precio de un instrumento financiero o el tamaño de un lote).

Tenga en cuenta que pueden producirse errores durante los cálculos matemáticos, lo que provocaría que el resultado no sea un número válido aunque tenga el tipo double (o float). Por ejemplo, una variable podría contener el resultado de calcular la raíz cuadrada de un número negativo.
 
Tales valores se denominan «Not a Number» (NaN, «No es un número») y se muestran al convertirlos a (string) como una breve indicación del tipo de error, por ejemplo, -nan(ind) (ind - indefinido), nan(inf) (inf - infinito). Al utilizar la función DoubleToString obtendrá un número grande que no tiene sentido.
 
Es especialmente importante que todos los cálculos posteriores con NaN también den NaN. Para comprobar estos valores, existe la función MathIsValidNumber.

 

long StringToInteger(string text)

La función convierte una cadena en un número del tipo long. Observe que el tipo de resultado es definitivamente long, y no int (a pesar del nombre) y no ulong.

Una forma alternativa es convertir el tipo utilizando el operador (long). Además, se puede utilizar cualquier otro tipo de entero de su elección para la conversión:(int), (uint), (ulong), etc.

Las reglas de conversión son similares a las del tipo double, pero excluyen el carácter de punto y el exponente de los caracteres permitidos.

string IntegerToString(long number, int length = 0, ushort filling = ' ')

La función IntegerToString convierte un entero del tipo long en una cadena de la longitud especificada. Si la representación numérica ocupa menos de un carácter, se rellena a la izquierda con un carácter filling (con un espacio por defecto). De lo contrario, el número se muestra en su totalidad, sin restricciones. Llamar a una función con parámetros por defecto equivale a hacer una conversión a (string).

Por supuesto, los tipos enteros más pequeños (por ejemplo, int, short) serán procesados por la función sin problemas.

En el script ConversionNumbers.mq5 se ofrecen ejemplos de uso de todas las funciones anteriores.

void OnStart()
{
   const string text = "123.4567890123456789";
   const string message = "-123e-5 buckazoid";
   const double number = 123.4567890123456789;
   const double exponent = 1.234567890123456789e-5;
   
   // type casting
   Print((double)text);    // 123.4567890123457
   Print((double)message); // -0.00123
   Print((string)number);  // 123.4567890123457
   Print((string)exponent);// 1.234567890123457e-05
   Print((long)text);      // 123
   Print((long)message);   // -123
   
   // converting with functions
   Print(StringToDouble(text)); // 123.4567890123457
   Print(StringToDouble(message)); // -0.00123
   
   // by default, 8 decimal digits
   Print(DoubleToString(number)); // 123.45678901
   
   // custom precision
   Print(DoubleToString(number5));  // 123.45679
   Print(DoubleToString(number, -5)); // 1.23457e+02
   Print(DoubleToString(number, -16));// 1.2345678901234568e+02
   Print(DoubleToString(number16)); // 123.4567890123456807
   // last 2 digits are not accurate!
   Print(MathSqrt(-1.0));                 // -nan(ind)
   Print(DoubleToString(MathSqrt(-1.0))); // 9223372129088496176.54775808
   
   Print(StringToInteger(text));      // 123
   Print(StringToInteger(message));   // -123
   
   Print(IntegerToString(INT_MAX));         // '2147483647'
   Print(IntegerToString(INT_MAX5));      // '2147483647'
   Print(IntegerToString(INT_MAX16));     // '      2147483647'
   Print(IntegerToString(INT_MAX16, '0'));// '0000002147483647'
}