Pregunta

tengo un método que se ocupa de unas coordenadas geográficas en .NET, y tengo una estructura que almacena un par de coordenadas tal que si 256 se hace pasar por una de las coordenadas, se convierte en 0. Sin embargo, en un caso particular, un valor de aproximadamente 255.99999998 se calcula, y por lo tanto almacena en la struct. Cuando se imprime en ToString (), se convierte en 256, lo que no debería ocurrir - 256 debe ser 0. No me importaría si se imprime 255.9999998 pero el hecho de que se imprime 256 cuando en la pantalla de depuración 255.99999998 es un problema. Tener que tanto almacenar y mostrar 0 sería aún mejor.

En concreto hay un problema con la comparación. 255.99999998 está suficientemente cerca de 256 tal que debe ser igual a ella. ¿Qué debo hacer cuando se comparan dobles? utilizar algún tipo de valor épsilon?


EDIT:. En concreto, mi problema es que me tome un valor, realizar algunos cálculos, a continuación, realizar los cálculos opuestos en ese número, y necesito recuperar el valor original exactamente

¿Fue útil?

Solución

Usted podría utilizar el enfoque épsilon, pero la épsilon es típicamente un fudge de moverse por el hecho de que la aritmética de punto flotante es con pérdida.

Se podría considerar evitar binario de puntos flotantes por completo y usar una buena clase racional.

El cálculo anterior fue probablemente destinado a ser 256 si estuviera haciendo aritmética sin pérdidas a medida que se obtendría con un tipo racional.

tipos racionales pueden ir por el nombre de la clase de relación o fracción, y son bastante simples de escribir

He aquí una ejemplo . Aquí es otra


Editar ....

Para entender su problema consideran que cuando el valor decimal 0.01 se convierte en una representación binaria que no se puede almacenar exactamente en la memoria finita. La representación hexadecimal para este valor es 0.028F5C28F5C donde el "28F5C" repite infinitamente. Así que incluso antes de hacer cualquier cálculo, de que pierda exactitud simplemente mediante el almacenamiento de 0,01 en formato binario.

clases racionales y decimales se utilizan para superar este problema, aunque con un costo de rendimiento. tipos racionales evitar este problema mediante el almacenamiento de un numerador y un denominador para representar a su valor. uso tipo decimal un binario codificado decimal formato , que puede ser con pérdidas en la división, pero puede almacenar valores decimales comunes exactamente.

Para su propósito todavía sugieren un tipo racional.

Otros consejos

Esto suena como un problema con la forma en que se imprime el número, no la forma en que se almacena. Un double tiene alrededor de 15 cifras significativas, por lo que puede decir 255.99999998 de 256 con una precisión de repuesto.

Puede elegir las cadenas de formato que debe le permiten mostrar tanto del número como te gusta.

La forma más habitual de comparar los dobles por la igualdad es restar ellos y ver si el valor absoluto es menor que algún épsilon predefinido, tal vez 0,000001.

Usted tiene que decidir a sí mismo en un umbral por debajo del cual dos valores son iguales. Este equivale a utilizar los llamados Los números de punto fijo (a diferencia de punto flotante). Entonces, usted tiene que realizar la ronda hasta manualmente.

Me gustaría ir con algún tipo sin signo con tamaño conocido (por ejemplo. Uint32 o uint64 si están disponibles, no sé .NET) y tratarlo como un punto fijo de tipo de número 256 mod.

Ej.

typedef uint32 fixed;

inline fixed to_fixed(double d)
{
    return (fixed)(fmod(d, 256.) * (double)(1 << 24))
}

inline double to_double(fixed f)
{
    return (double)f / (double)(1 << 24);
}

o algo más elaborado para adaptarse a una convención de redondeo (para más cercano, para bajar, a lo superior, a impar, incluso). Los más altos 8 bits de retención fija la parte entera, los 24 bits inferiores sostienen la parte fraccionaria. la precisión absoluta es 2 ^ {- 24}

.

Tenga en cuenta que la suma y restando un número tan naturalmente se envuelve alrededor de 256. Para la multiplicación, usted debe tener cuidado.

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