¿Es NAN adecuada para comunicar que un parámetro no válido estuvo involucrado en un cálculo?

8

Actualmente estoy trabajando en un sistema de procesamiento numérico que se implementará en un entorno de rendimiento crítico. Toma entradas en forma de matrices numéricas (éstas usan la biblioteca eigen , pero para el propósito de esta pregunta que es quizás irrelevante), y realiza una serie de cálculos numéricos (productos de matriz, concatenaciones, etc.) para producir salidas.

Todas las matrices se asignan de forma estática y sus tamaños se conocen en tiempo de compilación. Sin embargo, algunas de las entradas pueden no ser válidas. En estos casos excepcionales , todavía queremos que se calcule el código y queremos que se utilicen salidas no "contaminadas" por valores no válidos.

Para dar un ejemplo, tomemos el siguiente ejemplo trivial (esto es pseudo-código):

Matrix a = {1, 2, NAN, 4}; // this is the "input" matrix
Scalar b = 2;
Matrix output = b * a; // this results in {2, 4, NAN, 8}

La idea aquí es que 2, 4 y 8 son valores utilizables, pero la NAN debe indicar al destinatario de los datos que esa entrada estuvo involucrada en una operación que involucró un valor no válido, y debería descartarse (esto será detectado mediante una verificación std::isfinite(value) antes de utilizar el valor).

¿Es esta una buena forma de comunicar y propagar valores inutilizables, dado que el rendimiento es crítico y la asignación de almacenamiento dinámico no es una opción (y tampoco lo son otras construcciones que consumen recursos como boost::optional o punteros)?

¿Hay mejores maneras de hacer esto? En este punto, estoy bastante satisfecho con la configuración actual, pero esperaba obtener algunas ideas nuevas o críticas productivas de la implementación actual.

    
pregunta quant 20.08.2014 - 03:26

2 respuestas

7

Esta es una manera completamente razonable de ir. Tenga en cuenta también que hay varias máscaras de bits que se interpretan como NaN. Hay dos tipos principales de NaN: señalización (que puede generar una excepción cuando se crean, dependiendo de su configuración) y silenciosa (lo que nunca ocurre). Sin embargo, incluso dentro de las NaN silenciosas, hay varias máscaras de bits que corresponden a las NaN silenciosas. Si desea realmente meterse en él, puede crear sus propios NaN que sean distintos de los NaN normales. Por ejemplo, podría usar un patrón de bits específico que correspondería a NA (que es un concepto diferente al de NaN).

En cuanto a su punto sobre la contaminación. Esto se vuelve mucho más complicado. En general, cualquier operación matemática que involucre NaN da como resultado NaN. En otras palabras, NaN es contagiosa. En algunos casos, esto es lo que quieres. En otros, no lo es. Por ejemplo, supongamos que le pidieron la media del vector que dio. ¿Es NaN, o 7/3? Sin embargo, el producto vectorial escalar * que proporcionó funcionará exactamente de la manera que usted desea, y tampoco necesita realizar ninguna comprobación std::isfinite . Multiplica los números y la NaN saldrá automáticamente, por lo que es bastante eficaz. Si desea obtener una media de 7/3 sin embargo para su vector, necesita ser más inteligente, porque hacerlo ingenuamente resultará en NaN. Si bien no puedo decirte cómo hacer una implementación rápida de esto, numpy tiene uno, y su código abierto, para que puedas verlo.

    
respondido por el Nir Friedman 20.08.2014 - 04:49
1

Me parece bien, siempre y cuando tengas el modelo de punto flotante fijo y hayas dicho semántica de NaN.

IEEE 754 es suficiente en tu caso.

enlace

enlace

    
respondido por el Thomas Eding 20.08.2014 - 04:27

Lea otras preguntas en las etiquetas