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

pregunta creada en Mon, Feb 4, 2013 12:00 AM

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

Sé que 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 a 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
  1. ¿Por qué quieres usar un número decimal como clave en un diccionario? Puede ayudarnos a darle la mejor solución.
    2013-02-04 18: 59: 43Z
  2. Mi instrumento devuelve una lista para cada elemento en una lista de ángulos de entrada. Por lo tanto, el mapeo natural del dominio sería un diccionario donde cada clave es un número real (en el sentido matemático). Este número se usaría en los cálculos, pero una precisión de aproximadamente seis dígitos estaría bien (el instrumento tiene una precisión mucho menor).
    2013-02-04 19: 08: 38Z
  3. OK, pero ¿por qué un Diccionario? ¿Cuáles son los valores del diccionario?
    2013-02-04 19: 09: 38Z
  4. Los valores son una lista de posiciones de píxeles en una fotografía donde se ha proyectado un patrón de franja horizontal, y cada franja tiene un ángulo con el plano horizontal.
    2013-02-04 19: 11: 22Z
  5. @ CédricBignon pero para ser honesto, creo que los ángulos no son la entrada real, sino más bien un atributo de un objeto de "franja" o "franja". Quizás reformularé mi implementación, pero la pregunta de "valores numéricos como claves de diccionario" sigue siendo válida y relevante :)
    2013-02-04 19: 12: 42Z
3 Respuestas                              3                         

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", debe hacerlo clave personalizada que redondearía los valores de alguna manera conocida para poner resultados similares en el mismo cubo ...

    
6
2013-02-04 19: 08: 28Z
  1. O puede usar un comparador personalizado para proporcionar la misma funcionalidad sin claves personalizadas, pero con los decimales.
    2013-02-04 19: 12: 24Z

Si está utilizando decimal o double porque 0600350991100101035062 no es lo suficientemente grande, considere usar int en su lugar.

Además, creo que comparar longs o decimals debería estar bien siempre que no haya una fracción /parte decimal, y contenga solo números enteros (-1,0,1,2,3, etc.)

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

Si solo tratas con una precisión de 6 dígitos, la conversión a double debería estar bien.

    
1
2013-02-04 19: 26: 36Z
  1. ¡Buena respuesta, gracias!
    2013-02-04 20: 03: 23Z

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

Realmente necesitaba claves flotantes.

Por supuesto, me topé con los problemas de precisión y mi diccionario era mucho más grande de lo que tenía que ser (por ejemplo, int y 1.0 para ser tratado como el mismo). El uso de un número fijo de dígitos decimales no es una gran solución (por ejemplo, convertirlo en una cadena como lo propone OP), ya que utiliza un error absoluto para la comparación, mientras que un error relativo es mucho más universal.

Terminé escribiendo el siguiente método:

0.999998

Cuantifico las flotaciones usando este método antes de almacenarlo en el diccionario. El error relativo máximo permitido puede ser controlado por la constante (actualmente es 0.1%).

PS:

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;
}
es la clase de Unity. Se puede modificar fácilmente para usar el estándar Mathf.     
1
2016-03-18 17: 20: 41Z
Math
fuente colocada aquí