Pregunta

Estoy escribiendo algoritmos que trabajan en la serie de datos numéricos, en donde a veces, un valor de la serie debe ser null.Sin embargo, debido a que esta aplicación es de rendimiento crítico, he evitado el uso de tipos que aceptan valores null.He perf probado los algoritmos específicamente para comparar el rendimiento de la utilización de tipos que aceptan valores null vs no-tipos que aceptan valores null, y en el mejor de los casos tipos que aceptan valores null 2x más lento, pero a menudo mucho peor.

El tipo de datos más frecuentemente utilizada es doble, y en la actualidad la alternativa elegida a null es doble.NaN.Sin embargo entiendo que este no es exactamente el uso previsto para el valor NaN, así que estoy seguro de que si hay algún problema con este no puedo prever y cuál es la mejor práctica sería.

Estoy interesado en saber cuál es la mejor null alternativas para los siguientes tipos de datos, en particular:doble/float, decimal, DateTime int/largo (aunque otros no son más que bienvenidos)

Editar:Creo que tengo que aclarar mis necesidades en cuanto a rendimiento.Conciertos de datos numéricos se procesan a través de estos algoritmos en un tiempo que toma varias horas.Por lo tanto, aunque la diferencia entre por ejemplo 10ms o 20ms es generalmente insignificante, en este escenario lo que realmente no tiene un impacto significativo a la hora de la toma.

¿Fue útil?

Solución

Bueno, si usted ha descartado Nullable<T>, que se quedan con valores de dominio - es decir, un número mágico que te tratan como nulo. Si bien esto no es ideales , no es raro, ya sea - por ejemplo, muchas de las principales delicias de código marco DateTime.MinValue mismo como nulo. Esto, al menos, mueve el daño lejos de los valores comunes ...

editar para resaltar únicamente cuando no haya NaN

Entonces, ¿dónde no hay NaN, tal vez usar .MinValue - pero recuerda lo que sucede males si accidentalmente utilizar ese mismo valor que significa el mismo número ...

Es evidente que para los datos sin signo que necesita .MaxValue (evite cero !!!).

En lo personal, me gustaría tratar de utilizar Nullable<T> como la expresión de mi intención con mayor seguridad ... puede haber formas de optimizar su código Nullable<T>, tal vez. Y también - en el momento en que se haya registrado para el número mágico en todos los lugares que usted necesita, tal vez no va a ser mucho más rápido que Nullable<T>

Otros consejos

I algo en desacuerdo con Gravell en este caso borde específica: una variable Null-ed se considera 'no definido', que no tiene un valor. Así que lo que se utiliza para indicar que está bien: incluso los números mágicos, pero con números mágicos hay que tener en cuenta que un número mágico siempre te perseguirá en el futuro, cuando se convierte en un valor 'válida' de repente. Con Double.NaN usted no tiene que tener miedo de que: nunca va a convertirse en un doble válida. Sin embargo, usted tiene que considerar que NaN en el sentido de la secuencia de dobles sólo se puede utilizar como un marcador para 'no definido', no se puede utilizar como un código de error en las secuencias, así, obviamente.

Así que cualquier cosa que se utiliza para marcar 'indefinido': tiene que ser claro en el contexto del conjunto de valores que ese valor específico se considera el valor para 'indefinido' y que no va a cambiar en el futuro.

Si anulable le dan demasiados problemas, utilizar NaN, o cualquier otra cosa, siempre y cuando se tiene en cuenta las consecuencias: el valor elegido representa 'indefinido' y que permanecerá.

Estoy trabajando en un gran proyecto que utiliza NaN como un null valor.No estoy del todo cómodo con él - por razones similares como el tuyo:no saber lo que puede salir mal.No hemos encontrado ningún problema real hasta el momento, pero hay que ser conscientes de lo siguiente:

NaN aritmética de - Mientras, la mayoría de las veces, "NaN promoción" es una buena cosa, puede que no siempre sea lo que usted espera.

Comparación - Comparación de los valores queda bastante caro, si quieres NaN para comparar la igualdad.Ahora, las pruebas de flota para la igualdad no es simple de todos modos, pero el pedido (un < b) pueden llegar a ser realmente feo, porque nan a veces necesitan ser más pequeñas, a veces más grandes que los valores normales.

Código De La Infección - Veo a un montón de aritmética código que requiere manejo específico de NaN de ser correcta.Así que al final termina con "las funciones que aceptan NaN" y "funciones" que no" por razones de rendimiento.

Otros no lo finito NaN es npara el único no-finito valor.Debe tenerse en mente...

Excepciones De Punto Flotante no son un problema cuando se deshabilita.Hasta que alguien les permite.La verdadera historia:Estática intialization de una NaN en un control ActiveX.No suena de miedo, hasta que cambie de instalación para uso InnoSetup, que utiliza un Pascal/Delphi(?) core, que tiene FPU excepciones habilitado de forma predeterminada.Me tomó un tiempo para averiguar.

Así que, con todo, no es nada grave, aunque prefiero no tener en cuenta los valores Nan que a menudo.


Me gustaría utilizar tipos que aceptan valores null como a menudo como sea posible, a menos que sean (que ha demostrado ser) rendimiento / recursos a las restricciones.Un caso podría ser de gran vectores / matrices con ocasionales Nan, o grandes conjuntos de valores individuales donde el valor predeterminado NaN comportamiento es correcto.


Alternativamente, usted puede utilizar un índice del vector de vectores y matrices, estándar "sparse matrix" implementaciones, o en otro tipo bool/bit vector.

Respuesta parcial:

Float y Double proporcionan NaN (Not a Number). NaN es un poco complicado, ya que, por casualidad, NaN! = NaN. Si desea saber si un número es NaN, tendrá que utilizar Double.IsNaN ().

de punto flotante binario y .NET .

Tal vez la disminución significativa del rendimiento ocurre cuando se llama a uno de los miembros o propiedades de anulables (boxeo).

Trate de usar una estructura con la doble + un booleano indica si se especifica o no el valor.

Uno puede evitar algunos de la degradación del rendimiento asociado con Nullable<T> mediante la definición de su propia estructura

struct MaybeValid<T>
{
    public bool isValue;
    public T Value;
}

Si se desea, se puede definir constructor, o un operador de conversión de T a MaybeValid<T>, etc., pero el uso excesivo de tales cosas puede dar un rendimiento subóptimo. -estructuras expuestas al campo puede ser eficaz si se evita la copia de datos innecesarios. Algunas personas pueden fruncir el ceño a la noción de campos expuestos, pero pueden ser más eficientes que masivamente propiedades. Si una función que devuelva un T tendría que tener una variable de tipo T para mantener su valor de retorno, utilizando un MaybeValid<Foo> simplemente aumenta en un 4 el tamaño de lo que se devuelve. Por el contrario, el uso de un Nullable<Foo> requeriría que la primera función de calcular el Foo y luego pasar una copia de la misma al constructor para la Nullable<Foo>. Además, el retorno de una Nullable<Foo> requerirá que cualquier código que quiere utilizar el valor devuelto debe hacer al menos una copia adicional a una ubicación de almacenamiento (variable o temporal) de tipo Foo antes de que pueda hacer algo útil con él. Por el contrario, el código puede utilizar el campo Value de una variable de tipo Foo casi tan eficientemente como cualquier otra variable.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top