La documentación recomienda que use G17 en lugar de R , ya que R a veces puede fallar en el viaje de ida y vuelta.
Sin embargo, (1.0/10).ToString("G17") da "0.10000000000000001" , que es bastante horrible. mientras que el formato de ida y vuelta parece funcionar bien (y da "0.1" ). Estoy feliz de pasar algunos ciclos de CPU para obtener un resultado más estético. Pero las posibles fallas de ida y vuelta son más preocupantes.
¿Para qué tipo de valores (dobles) R falla en el viaje de ida y vuelta? ¿Y qué tan mal? ¿La versión de .Net (ejecutamos tanto en Net Framework 4.72 como en NetCore 3.1) afecta las cosas? ¿Escribir en una plataforma y leer en otra podría hacer que las fallas de ida y vuelta sean más frecuentes?
Estamos considerando escribir dobles en R primero, analizando para verificar el viaje de ida y vuelta y retrocediendo a G17 solo si eso falla. ¿Hay una mejor manera de obtener resultados confiables y bien formateados?
El viaje de ida y vuelta aquí es un valor numérico que se convierte en una cadena que se analiza nuevamente en el mismo valor numérico .
La consternación de OP con (1.0/10). ToString ("G17") da "0.10000000000000001", que es bastante horrible. es una evaluación incorrecta del éxito de ida y vuelta. La cadena intermedia es solo la mitad del viaje de ida y vuelta .
Double codifica exactamente alrededor de 2 64 valores diferentes. Todos los valores codificables son algún número entero limitado * 2 some_power . 0.1 no es uno de ellos. 1.0/10 hace un cociente matemático de 0.1, pero un valor Double ligeramente diferente. El valor Double más cercano y sus dos vecinos Double más cercanos:
Before 0.099999999999999991673... 0.100000000000000005551... After 0.100000000000000019428... OP report 0.10000000000000001 Digit count 12345678901234567El ejemplo de OP debería ser <(0.1000000000000000005551).ToString("G17") da "0.10000000000000001"> que es bueno .
Imprimir un Double con G17 proporciona 17 dígitos significativos, suficientes para un viaje de ida y vuelta con éxito.
¿Para qué tipo de valores (dobles) R falla en el viaje de ida y vuelta? ¿Y qué tan mal?
Para esto, me baso en la memoria. R a veces usaba menos de 17 dígitos significativos, como 15, para formar la cadena intermedia. El algoritmo utilizado para determinar el recuento de dígitos a veces se quedó un poco corto y, por lo tanto, "algunos casos no logran redondear con éxito el valor original".
Usar G17 siempre funciona. Para algunos valores, menos de 17 también habría funcionado. La desventaja de G17 es exactamente en casos como este. Menos de 17 dígitos habrían funcionado y habrían proporcionado una cadena intermedia más agradable y más corta.
Una cadena agradable y legible por humanos no es el objetivo del viaje de ida y vuelta. El objetivo es formar el mismo Double después de pasar de valor a cadena a valor, incluso si la cadena intermedia tiene dígitos adicionales en casos seleccionados.
¿Hay una mejor manera de obtener resultados confiables y bien formateados?
"bien formateado" es una carga adicional para el viaje de ida y vuelta . MS intentó hacerlo con R y falló en algunos casos, prefiriendo conservar la misma funcionalidad rota que arreglarla.
Sería prudente que OP evitara ese camino y renunciara al objetivo de una cadena intermedia bien formateada y se centrara en el objetivo de ida y vuelta de recuperar el mismo valor final.
Utilice G17 .
Estamos considerando escribir dobles en R primero, analizando para verificar el viaje de ida y vuelta y retrocediendo a G17 solo si eso falla.
Eso funcionaría si se hace correctamente. Para evaluar la corrección, pruebe su código con muchos valores y también publíquelo junto con el arnés de prueba para la revisión del código.