Lamentablemente, las operaciones de punto flotante soon se vuelven inexactas, cuando se supera la precisión de mantissa, los resultados se redondean. Una vez que se introduce un "error" de redondeo, se acumulará en operaciones posteriores ...
Por lo tanto, generalmente NO, no puede usar ese ingenuo algoritmo para convertir decimales arbitrarios, esto puede conducir a un número incorrectamente redondeado , apagado por varios ulp del correcto, como otros ya te han dicho.
pero vamos a ver lo lejos que puede ir:
Si reconstruye cuidadosamente el flotador como esto:
if(biasedExponent >= 0)
return integerMantissa * (10^biasedExponent);
else
return integerMantissa/(10^(-biasedExponent));
existe el riesgo de exceder la precisión tanto cuando acumulando la integerMantissa si tiene muchos dígitos, y al aumentar 10 a la potencia de BiasedExponent ...
Afortunadamente, si las dos primeras operaciones son exactas, entonces puede permitirse una operación final inexacta * o /, gracias a IEEE propert ies, el resultado se redondeará correctamente.
Vamos a aplicar esto a los flotadores de precisión simple que tienen una precisión de 24 bits.
10^8 > 2^24 > 10^7
Observando que múltiplo de 2 sólo aumentará el exponente y dejar la mantisa sin cambios, sólo tenemos que hacer frente a las potencias de 5 para la exponenciación de 10:
5^11 > 2^24 > 5^10
Sin embargo, puede darse el lujo 7 dígitos de precisión en el integerMantissa y una biasedExponent entre -10 y 10.
en doble precisión, 53 bits,
10^16 > 2^53 > 10^15
5^23 > 2^53 > 5^22
Así que puede pagar 15 dígitos decimales, y un exponente sesgado entre -22 y 22.
Todo depende de usted para ver si sus números siempre se sitúen en el rango correcto ... (Si usted es realmente complicado , puede organizar equilibrar mantisa y exponente mediante la inserción/eliminación de ceros finales).
De lo contrario, tendrá que utilizar un poco de precisión extendida.
Si su lenguaje proporciona números enteros de precisión arbitraria, entonces es un poco difícil de hacerlo bien, pero no es tan difícil, lo hice en Smalltalk y escribió en su blog acerca de ello en http://smallissimo.blogspot.fr/2011/09/clarifying-and-optimizing.html y http://smallissimo.blogspot.fr/2011/09/reviewing-fraction-asfloat.html
Tenga en cuenta que estos son implementaciones sencillas e ingenuas . Afortunadamente, libc está más optimizado.
@Nils: Está ignorando los modos de redondeo, et al. Eche un vistazo a strtod para tener una idea de lo que es necesario. – user7116
Sí, lo sé. Hay aún más que he omitido, como manejar denormales y ceros. Pero me pareció que el póster original quería hacerlo con fines de aprendizaje, no para producción. –
Parcialmente cierto. Quiero leer un flotador de una cuerda, pero hay otras cosas que lo siguen dentro de la cuerda. Java no puede manejar eso. Pero dado que el problema resulta ser tan diabólicamente difícil, simplemente analizaré el flotador, lo pondré en una cadena y lo lanzaré a Float.parseFloat();) – Thomas