Pregunta

Estoy realizando algunas conversiones de tipos de datos donde necesito representar uint, long, ulong y decimal como valores de punto flotante doble IEEE 754.Quiero poder detectar si el tipo de datos IEEE 754 no puede contener el valor antes de realizar la conversión.

Una solución de fuerza bruta sería envolver un try-catch alrededor de un yeso para buscar dos veces. OverflowException.Leyendo algunos de los Documentación CLR implica que algunas conversiones simplemente cambian silenciosamente el valor sin excepciones.

¿Existe alguna forma infalible de realizar esta comprobación?Busco integridad sobre facilidad de implementación.Tengo la sensación de que voy a leer atentamente la especificación IEEE 754 y comprobar matissa y exponente cuidadosamente...

Debo agregar que soy mayoría preocupado por representar números enteros con precisión y que la pérdida de precisión de punto flotante es una preocupación secundaria (pero aún así vale la pena considerarla).

EDITAR: Int32 puede expresarse completamente como IEE-754.También el Decimal El tipo de datos es una gran parte de la pregunta.

Actualización importante: Si te refieres a esta pregunta, también deberías leer esta pregunta: IEEE-754 Doble (coma flotante de 64 bits) vs.Largo (entero de 64 bits) revisado

Observa un error en la respuesta donde algunos valores muy grandes también pueden representarse exactamente mediante IEEE-754.Si bien esto puede significar que el valor será de ida y vuelta correctamente, para mi propósito original (será de ida y vuelta a JavaScript) no será así.

También parece haber un error en el tipo CLR System.Double porque no permite correctamente que estos valores realicen un viaje de ida y vuelta.

¿Fue útil?

Solución

La solución simple podría ser algo como ( si x es un int ):

if ((int)(double)x != x) { 
  // won't convert
} else {
  // will convert
}

y así por mucho tiempo, etc.

(doble) x convertirá x de un int a un doble. El (int) luego lo convierte de nuevo. Entonces (int) (double) x convierte de int a double y luego de regreso. Esencialmente, el código verifica que la conversión a doble sea reversible (y, por lo tanto, que el doble pueda almacenar el valor exacto de int).

Otros consejos

Esto depende principalmente del rango de números con el que está operando. Siempre que esté dentro de los 15 dígitos (para un doble ), debe estar en el lado seguro para números enteros.

Básicamente, lo que debe tener en cuenta es la cantidad de dígitos significativos. Por lo tanto, siempre que su número sea menor que el límite de dígitos significativo, seguirá siendo exacto; si se hace más grande, perderá precisión (incluso si se trata de números enteros).

Entonces, mientras su número sea < 2 ^ 53, generalmente eres bueno.

IEEE 754 Double tiene 52 bits para mantissa y está convirtiendo de / a entero / largo por lo que es bastante fácil de probar. Si su número entero consume menos de 52 bits, entonces debería ser convertible sin problemas a IEEE 754 doble.

Supongo (lo sé con certeza en el caso de Java, pero no C # y lazy para comprobar) que int es de 32 bits y largo es de 64 bits. Entonces, seguro que int puede caber en doble sin ningún problema, tanto firmar como cancelar firma.

Para ulong, simplemente si todos los bits más altos que el bit 52 son uno como ((aULong & amp; & amp; 0xFFF0000000000000) == 0).

Durante mucho tiempo, debe traer su signo a la consideración. Dado que Long es el segundo complemento, pero IEEE754 no lo es (solo tiene un bit negativo), cree que es seguro encubrir negativo largo a positivo (* -1) y verificar como positivo. Entonces, si el largo es negativo, cronometra con -1 primero (no hagas nada positivo). Luego, compruébalo como ulong.

Espero que esto ayude.

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