Pregunta ¿Debo usar el tipo decimal como claves en un diccionario?


Estoy a punto de crear un diccionario donde cada valor tiene una clave numérica, obtenida por un cálculo experimental.

Yo sé eso double y cualquier otro tipo de punto flotante no es adecuado para ser usado como una clave, ya que es difícil comparar dos números de punto flotante con respecto a la unicidad o la igualdad.

¿Alguien sabe si Decimal ¿Es un buen candidato con este respecto? La alternativa sería convertir el doble en una cadena con una precisión dada, pero eso me suena como una solución poco elegante.


5
2018-02-04 18:57


origen


Respuestas:


No hay mucha diferencia entre usar float o decimal como clave en el diccionario. Ambos representan el número con exponente, por lo que ambos sufren el mismo problema de comparación en una escala diferente.

Cualquiera de los dos estaría bien para el diccionario si necesita igualdad de bits, si necesita las claves para "aproximadamente el mismo valor", necesita hacerla clave personalizada que redondearía los valores de alguna manera conocida para poner resultados similares en el mismo grupo. ..


6
2018-02-04 19:08



Si estás usando decimal o double porque int no es lo suficientemente grande, considera usar long en lugar.

Además, creo que comparando decimals o doubles debe estar bien siempre y cuando no haya una fracción / parte decimal, y contenga solo números enteros (-1,0,1,2,3, etc.)

(Aunque no recomiendo usar decimal/double donde la comparación es importante para evitar futuros errores inesperados)

Si solo se trata de una precisión de 6 dígitos, entonces int debería estar bien.


2
2018-02-04 19:13



Sé que esta es una vieja pregunta, pero creo que mi respuesta podría ayudar a alguien.

Realmente necesitaba llaves flotantes.

Por supuesto, me topé con los problemas de precisión y mi diccionario era mucho más grande de lo que debía ser (lo quería, por ejemplo, 1.0 y 0.999998 ser tratado como el mismo). Usar una cantidad fija de dígitos decimales no es una gran solución (por ejemplo, convertirla en una cadena como lo propone OP) ya que usa un error absoluto para la comparación, mientras que el error relativo es mucho más universal.

Terminé escribiendo el siguiente método:

float Quantize(float x)
{
    const float relMaxQuantError = 0.001f;

    float ret = Mathf.Log10(Mathf.Abs(x));
    float quantum = Mathf.Log10(1+relMaxQuantError); 
    ret = Mathf.Floor(ret/quantum) * quantum;
    ret = Mathf.Sign(x) * (Mathf.Pow(10, ret));

    return ret;
}

Yo cuantifico los flotadores usando este método antes de almacenarlo en el diccionario. El máximo error relativo permitido se puede controlar const (actualmente es 0.1%).

PD: Mathf Es la clase de Unity. Se puede ajustar fácilmente para usar el estándar Math.


1
2018-03-18 17:20