2010-10-18 10 views
9

Me han dado la tarea de usar Java para producir una tabla Sin, sin embargo, parece que obtengo algunos resultados muy extraños para algunos valores de la entrada. Estoy utilizando el siguienteComportamiento extraño de Java con Sin y ToRadians

System.out.println("| sin(" + currentPoint + ") = " + Math.sin(Math.toRadians(currentPoint))); 

Dónde (int) punto actual es un valor en grados (por ejemplo 90)

Estos son los resultados que encuentro raro

| sin(360) = -2.4492935982947064E-16 
| sin(180) = 1.2246467991473532E-16 
| sin(150) = 0.49999999999999994 
| sin(120) = 0.8660254037844387 

Esperando

sin(360) = 0 
sin(180) = 0 
sin(150) = 0.5 
sin(120) = 0.866025404 

¿Me está faltando algo?

+1

Según [Google] (http://www.google .com/search? sourceid = chrome & ie = UTF-8 & q = sin + 360 + grados), 'sin (360 degrees)' es de hecho '0'. ¿Estás seguro de que te refieres a seno? –

+1

sus resultados esperados están interpretando los valores como radianes, mientras que en su programa los está considerando como mediciones de grados. –

+1

Su código es correcto, las expectativas son incorrectas. – Ishtar

Respuesta

7

Usted está tratando con números de punto flotante, en busca de respuestas exactas no va a funcionar para todos los valores. Eche un vistazo a What Every Computer Scientist Should Know About Floating-Point Arithmetic. Quiere que sus pruebas sean equivalentes a sus expectativas dentro de algún delta. Tenga en cuenta que las respuestas que recibe son bastante cercanas. Expresa valores en bits que te muerden.

Desde el enlace:

Exprimir un número infinito de números reales en un número finito de bits requiere una representación aproximada. Aunque hay infinitos enteros, en la mayoría de los programas el resultado de los cálculos enteros se puede almacenar en 32 bits. Por el contrario, dado un número fijo de bits, la mayoría de los cálculos con números reales producirán cantidades que no se pueden representar exactamente utilizando tantos bits. Por lo tanto, el resultado de un cálculo de punto flotante a menudo debe redondearse para volver a su representación finita. Este error de redondeo es la característica del cálculo en coma flotante.

2

Si el código fue System.out.println("| sin(" + currentPoint + ") = " + Math.sin(currentPoint)); que se puede esperar esto:

sin(360) = 0.958915723 
sin(180) = -0.801152636 
sin(150) = -0.71487643 
sin(120) = 0.580611184

En otras palabras, el seno de 360 ​​radianes es 0,9589, pero el seno de 360 ​​grados es 0.

EDIT:
La razón por la que está viendo resultados inesperados es solo debido a la falta de precisión en los cálculos. Si acaba de formatear los resultados para que tengan menos lugares decimales, el redondeo se encargará de ello. Hacer algo como esto:

System.out.printf("| sin(%d) = %.7f\n", currentPoint, Math.sin(Math.toRadians(currentPoint)));

por lo que recibirá los resultados más cerca de lo que espera.

+0

No tengo ninguna de estas opciones ..? –

+0

Pez: Sus resultados son correctos, simplemente tienen un formato pobre. – Gabe

1

Los carteles de arriba son correctos. Los valores correctos que usted está esperando son:

Sin (360 grados) = 0 Sin (180 grados) = 0 Sin (150 grados) = 0,5 Sin (120 grados) = 0,866

El el código está devolviendo las respuestas correctas. Solo necesitan ser redondeados. Prueba esto:

System.out.printf("%s%.3f","| sin(" + currentPoint + ") = ", (Math.sin(Math.toRadians(currentPoint)))); 

Puede cambiar el valor .3f a diferentes números si se quiere mejorar o reducir la precisión decimal.

Por alguna razón, muestra el pecado de 360 ​​en ser -0.00. Estoy seguro de que hay una solución más elegante, pero esto debería funcionar.

EDITAR: Batido por segundos. Usa el código arriba mío, es más fácil de leer.

0

A continuación se muestra la descripción de API del método Math.sin. Tenga en cuenta la parte en Astérix. Apuesto a que la diferencia entre los resultados esperados y los que obtiene una vez son defectos de cálculo del punto de flotación o problemas de redondeo.

pecado

pública pecado doble estática (double a)

Returns the trigonometric sine of an angle. Special cases: 

    * If the argument is NaN or an infinity, then the result is NaN. 
    * If the argument is zero, then the result is a zero with the 

mismo signo que el argumento.

A result must be within 1 **ulp** of the correctly rounded result. Results 

debe ser semi-monótono.

Parameters: 
    a - an angle, in radians. 
Returns: 
    the sine of the argument. 
1

También tenga en cuenta que Math.PI, que es un valor doble, no es PI, sino solo una aproximación de PI, y Math.sin (Math.PI) le da el doble valor que es el más cercano a real valor matemático de sin (Math.PI).

2

Sus resultados son correctos ... para la aproximación prueba este ...

result=Math.sin(Math.toRadians(value)); 
    result=format(result); 


    private double format(double value) { 
      return (double)Math.round(value * 1000000)/1000000; //you can change this to round up the value(for two position use 100...) 
     } 
2

Como se mencionó anteriormente, no es un error, sólo la aproximación de la aritmética de punto flotante de ordenador.

para obtener la respuesta esperada, como sin() & cos() son entre -1, 0, 1, intenta agregar 1 se redondea a la Precisión de necesario y restar 1.

x = round15(Math.sin(toRad(angle))+1)-1; 

donde round15 se define

public double round15(double x){ 
    DecimalFormat twoDForm = new DecimalFormat("0.##############E0"); 
    String str = twoDForm.format(x); 
    return Double.valueOf(str); 
} 

Funciona para mí, espero que a los futuros lectores les guste.

0

debe convertir el ángulo en radianes como este

Math.sin (Math.toRadians (90)) y el resultado debe ser 1

Cuestiones relacionadas