c ++ Sin y Cos

Estoy seguro de que esta es una pregunta realmente estúpida, pero cuando paso un ángulo de 180 grados en las funciones cos () y sin () de c / c ++ parece que recibo un valor incorrecto. Sé que debería ser: pecado de 0.0547 y cos de 0.99 pero obtengo el pecado de 3.5897934739308216e-009 y cos de -1.00000

Mi código es:

double radians = DegreesToRadians( angle ); double cosValue = cos( radians ); double sinValue = sin( radians ); 

DegreesToRadians () es:

 double DegreesToRadians( double degrees ) { return degrees * PI / 180; } 

Gracias 🙂

C / C ++ proporciona funciones sin(a) , cos(a) , tan(a) , etc. que requieren un parámetro con unidades radian en lugar de grados . double DegreesToRadians(d) realiza una conversión que es cercana pero aproximada a medida que se redondean los resultados de la conversión. También la máquina M_PI está cerca, pero no tiene el mismo valor que la matemática irracional π .

El código de OP con 180 pasó a DegreesToRadians(d) y luego a sin()/cos() da resultados que difieren de lo esperado debido al redondeo, precisión finita de double() y posible valor débil para PI .

Una mejora es realizar reducción de argumento en grados antes de llamar a la función trigonométrica. Lo siguiente reduce el ángulo primero a un rango de -45 ° a 45 ° y luego llama a sin() . Esto asegurará que los valores grandes de N en sind(90.0*N) --> -1.0, 0.0, 1.0 . . Nota: sind(360.0*N +/- 30.0) puede no ser exactamente igual a +/-0.5 . Algunas consideraciones adicionales son necesarias.

 #include  #include  static double d2r(double d) { return (d / 180.0) * ((double) M_PI); } double sind(double x) { if (!isfinite(x)) { return sin(x); } if (x < 0.0) { return -sind(-x); } int quo; double x90 = remquo(fabs(x), 90.0, &quo); switch (quo % 4) { case 0: // Use * 1.0 to avoid -0.0 return sin(d2r(x90)* 1.0); case 1: return cos(d2r(x90)); case 2: return sin(d2r(-x90) * 1.0); case 3: return -cos(d2r(x90)); } return 0.0; } int main(void) { int i; for (i = -360; i <= 360; i += 15) { printf("sin() of %.1f degrees is % .*e\n", 1.0 * i, DBL_DECIMAL_DIG - 1, sin(d2r(i))); printf("sind() of %.1f degrees is % .*e\n", 1.0 * i, DBL_DECIMAL_DIG - 1, sind(i)); } return 0; } 

Salida

 sin() of -360.0 degrees is 2.4492935982947064e-16 sind() of -360.0 degrees is -0.0000000000000000e+00 // Exact sin() of -345.0 degrees is 2.5881904510252068e-01 // 76-68 = 8 away // 2.5881904510252076e-01 sind() of -345.0 degrees is 2.5881904510252074e-01 // 76-74 = 2 away sin() of -330.0 degrees is 5.0000000000000044e-01 // 44 away // 0.5 5.0000000000000000e-01 sind() of -330.0 degrees is 4.9999999999999994e-01 // 6 away sin() of -315.0 degrees is 7.0710678118654768e-01 // 68-52 = 16 away // square root 0.5 --> 7.0710678118654752e-01 sind() of -315.0 degrees is 7.0710678118654746e-01 // 52-46 = 6 away sin() of -300.0 degrees is 8.6602540378443860e-01 sind() of -300.0 degrees is 8.6602540378443871e-01 sin() of -285.0 degrees is 9.6592582628906842e-01 sind() of -285.0 degrees is 9.6592582628906831e-01 sin() of -270.0 degrees is 1.0000000000000000e+00 // Exact sind() of -270.0 degrees is 1.0000000000000000e+00 // Exact ... 

En primer lugar, un coseno de 180 grados debe ser igual a -1 , por lo que el resultado obtenido es el correcto.

En segundo lugar, a veces no se pueden obtener los valores exactos al usar las funciones de sin/cos/tan etc. ya que siempre se obtienen resultados más cercanos a los correctos . En tu caso, el valor que obtuviste del sin es el más cercano a cero.

El valor de sin(PI) que obtuvo difiere de cero solo en el dígito noveno (!) Después del punto flotante. 3.5897934739308216e-009 es casi igual a 0.000000004 y eso es casi igual a cero.

Tengo el mismo problema que el OP al convertir la aplicación a 64 bits.
Mi solución es usar las nuevas funciones math.h __cospi () y __sinpi ().
El rendimiento es similar (incluso un 1% más rápido) que cos () y sin ().

 // cos(M_PI * -90.0 / 180.0) returns 0.00000000000000006123233995736766 //__cospi( -90.0 / 180.0) returns 0.0, as it should // #define degree2rad 3.14159265359/180 // #define degree2rad M_PI/ 180.0 // double rot = -degree2rad * ang; // double sn = sin(rot); // double cs = cos(rot); double rot = -ang / 180.0; double sn = __sinpi(rot); double cs = __cospi(rot); 

Desde math.h:

 /* __sinpi(x) returns the sine of pi times x; __cospi(x) and __tanpi(x) return the cosine and tangent, respectively. These functions can produce a more accurate answer than expressions of the form sin(M_PI * x) because they avoid any loss of precision that results from rounding the result of the multiplication M_PI * x. They may also be significantly more efficient in some cases because the argument reduction for these functions is easier to compute. Consult the man pages for edge case details. */