- El valor absoluto de un número
- Máximo y mínimo de dos números
- Funciones de redondeo
- Resto tras la división (operación módulo)
- Potencias y raíces
- Funciones exponenciales y logarítmicas
- Funciones trigonométricas
- Funciones hiperbólicas
- Prueba de normalidad para números reales
- Generación de números aleatorios
- Control de la codificación endian de números enteros
Prueba de normalidad para números reales
Dado que los cálculos con números reales pueden tener situaciones anómalas, como salirse del ámbito de una función, obtener infinito matemático o pérdida de orden, entre otras, el resultado puede no contener ningún número. En lugar de ello, puede contener un valor especial que describa realmente la naturaleza del problema. Todos estos valores especiales tienen un nombre genérico «no es un número» (Not A Number, NaN).
Ya nos hemos enfrentado a ellos en las secciones anteriores del libro. En concreto, cuando se envía a un diario (véase la sección De números a cadenas y viceversa) se muestran como etiquetas de texto (por ejemplo, nan(ind), +inf y otras). Otra característica es que un solo valor NaN entre los operandos de cualquier expresión es suficiente para que toda la expresión deje de evaluarse correctamente y comience a dar el resultado NaN. Las únicas excepciones son los «no números» que representan el más/menos del infinito: si divides algo por ellos, obtienes cero. Sin embargo, aquí hay una excepción esperada: si dividimos infinito por infinito, volvemos a obtener NaN.
Por lo tanto, es importante que los programas determinen el momento en que aparece NaN en los cálculos y manejen la situación de una manera especial: señalen un error, sustituyan algún valor por defecto aceptable o repitan el cálculo con otros parámetros (por ejemplo, reduzcan la precisión/el paso del algoritmo iterativo).
Hay dos funciones en MQL5 que le permiten analizar un número real para la normalidad:MathIsValidNumber da una respuesta simple: sí (true) o no (false), y MathClassify produce una categorización más detallada.
A nivel físico, todos los valores especiales se codifican en un número con una combinación especial de bits que no se utiliza para representar números ordinarios. Para los tipos double y float estas codificaciones son, por supuesto, diferentes. Echemos un vistazo a double entre bastidores (ya que tiene más demanda que float).
En el capítulo Plantillas anidadas creamos una clase Converter para cambiar de vista combinando dos tipos diferentes en una unión. Vamos a utilizar esta clase para estudiar el dispositivo de bits NaN.
Por comodidad, trasladaremos la clase a un archivo de encabezado independiente ConverterT.mqh. Vamos a conectar este archivo mqh en el script de prueba MathInvalid.mq5 y a crear una instancia de un conversor para un grupo de tipos double/ulong (el orden no es importante ya que el conversor es capaz de trabajar en ambas direcciones).
static Converter<ulong, double> NaNs; |
La combinación de bits en NaN está estandarizada, así que vamos a tomar algunos valores de uso común representados por las constantes ulong, y vamos a ver cómo reaccionan ante ellos las funciones integradas.
// basic NaNs
|
Como era de esperar, los resultados fueron los mismos.
Veamos la descripción formal de las funciones MathIsValidNumber y MathClassify, y continuemos con las pruebas.
bool MathIsValidNumber(double value)
La función comprueba la corrección de un número real. El parámetro puede ser del tipo double o float. El resultado true significa el número correcto, y false significa «no es un número» (una de las variedades de NaN).
ENUM_FP_CLASS MathClassify(double value)
La función devuelve la categoría de un número real (de tipo double o float) que es uno de los valores del enum ENUM_FP_CLASS:
- FP_NORMAL es un número normal.
- FP_SUBNORMAL es un número inferior al número mínimo representable de forma normalizada (por ejemplo, para el tipo double, se trata de valores inferiores a DBL_MIN, 2.2250738585072014e-308); pérdida de orden (precisión).
- FP_ZERO es cero (positivo o negativo).
- FP_INFINITE es infinito (positivo o negativo).
- FP_NAN significa todos los demás tipos de «no números» (subdivididos en familias de NaN «silenciosos» y «de señal»).
MQL5 no proporciona NaN de alerta que se utilizan en el mecanismo de excepciones y permite la interceptación y respuesta a errores críticos dentro del programa. No existe tal mecanismo en MQL5, así que, por ejemplo, en caso de una división cero, el programa MQL simplemente termina su trabajo (se descarga del gráfico).
Puede haber muchos NaN «silenciosos», y puede construirlos utilizando un conversor para diferenciar y manejar estados no estándar en sus algoritmos computacionales.
Realicemos algunos cálculos en MathInvalid.mq5 para visualizar cómo se obtienen los números de las distintas categorías.
// calculations with double
|
Podemos utilizar el convertidor en sentido contrario: para obtener su representación en bits mediante el valor double, y detectar así los «no números»:
PrintFormat("%I64X", NaNs[MathSqrt(-1.0)]); // FFF8000000000000
|
La función PrintFormat es similar a StringFormat; la única diferencia es que el resultado se imprime inmediatamente en el registro y no en una cadena.
Por último, asegurémonos de que los «no números» siempre sean no iguales:
// NaN != NaN always true
|
Para obtener NaN o infinito en MQL5 existe un método basado en la conversión de las cadenas «nan» e «inf» a double.
double nan = (double)"nan";
|