2011-10-05 11 views
6
código

siguiente me da 5.999999999999998 de resultado, pero la respuesta es correcta 6.precisión en Erlang

Alpha = math:acos((4*4 + 5*5 - 3*3)/(2*4*5)) 
Area = 1/2 * 4 * 5 * math:sin(Alpha) 

¿Es posible obtener 6?

+5

No tiene garantía de obtener resultados exactos al usar la aritmética de coma flotante. Este tema ha sido cubierto muchas, muchas, muchas veces. – Nayuki

Respuesta

23

Ha ejecutado en un problema tan común que tiene su propio sitio web, What Every Programmer Should Know About Floating-Point Arithmetic. El problema se debe a la forma en que la aritmética de punto flotante funciona en prácticamente todas las CPU del mercado que admiten aritmética de FP; no es específico de Erlang.

Si la aritmética de punto flotante regular no le proporciona la precisión o exactitud que necesita, puede utilizar una biblioteca aritmética de precisión arbitraria en lugar de la aritmética incorporada. Quizás la biblioteca más conocida sea GMP, pero tendría que envolverla en NIFs para usarla desde Erlang.

Hay at least one pure-Erlang alternative, pero no tengo experiencia con él, por lo que no puedo endorsarlo personalmente.

+0

Esto definitivamente es una lectura obligada para cualquiera que haga aritmética de coma flotante. – rvirding

+0

Muchas gracias por el enlace – Yola

+0

@WarrenYoung Gracias por la información, busqué y fundo esto: https://github.com/tim/erlang-decimal Pero no estoy seguro si está en desarrollo activo, pero algunos las personas tienen tenedores con cambios y nuevas características. – JHG

8

El cálculo se realiza utilizando aritmética de coma flotante estándar en su hardware. A veces aparecen errores de redondeo.

¿Realmente necesita 15 dígitos de precisión?

para obtener un valor más "exacta" hay varias opciones:

> round(Area). % Will round to integer 
6 

o se puede redondear a cierta precisión

round(Area * 10000000)/10000000. 
6.0 

Si el propósito es imprimir el valor, entonces la impresión con la salida predeterminada para flotantes le da menos precisión.

io:format("~f~n", [Area]). 
6.000000 
ok 

o con una precisión específica

io:format("~.14f~n", [Area]). 
6.00000000000000 
ok 

HTH