El pecado y los cos importan resultados inesperados para ángulos bien conocidos -- ++ campo con floating-point campo con trigonometry campo con cmath camp Relacionados El problema

Sin and Cos give unexpected results for well-known angles


3
vote

problema

Español

Estoy seguro de que esta es una pregunta realmente estúpida, pero cuando paso un ángulo de 180 grados en las funciones de C / C ++ COS () y SIN (), parezco recibir 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 );   

Degleestoradians () es:

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

Gracias :)

Original en ingles

I am sure this is a really stupid question, but when I pass an angle of 180 degrees into c/c++'s cos() and sin() functions I appear to receive an incorrect value. I know that it should be: sin of 0.0547 and cos of 0.99 but I get sin of 3.5897934739308216e-009 and cos of -1.00000

My code is:

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

DegreesToRadians() is:

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

Thank you :)

           
       
       

Lista de respuestas

13
 
vote
vote
La mejor respuesta
 

C / C ++ proporciona Libraries7 , Libraries8 , Libraries9 , etc. Funciones que requieren un parámetro con radian unidades en lugar de grados . +0 Realiza una conversión que se encuentra Cerrar Pero un aproximado a medida que se redondean los resultados de la conversión. También la máquina +1 está cerca, pero no el mismo valor que el Matemático Irracional Irracional +2 .

Código OP con +3 PASADO AL +4 y luego a +5 ofrece resultados que difieren de lo esperado debido a la redondeo, la precisión finita de +6 y posible un valor débil para +7 .

Una mejora es realizar una reducción de argumentos en grados antes de llamar a la función TRIG. La siguiente reduce el ángulo primero a un rango de A -45 ° a 45 ° y luego llama +8 . Esto asegurará que los valores grandes de +9 en jcommon-1.0.23.jar0 . . NOTA: jcommon-1.0.23.jar1 Es posible que no sea exactamente igual jcommon-1.0.23.jar2 . Algunas consideraciones adicionales necesarias.

  jcommon-1.0.23.jar3  

Salida

  jcommon-1.0.23.jar4  
 

C/C++ provides sin(a), cos(a), tan(a), etc. functions that require a parameter with radian units rather than degrees. double DegreesToRadians(d) performs a conversion that is close but an approximate as the conversion results are rounded. Also machine M_PI is close, but not the same value as the the mathematical irrational xcfx80.

OP's code with 180 passed to DegreesToRadians(d) and then to sin()/cos() gives results that differ than expected due to rounding, finite precision of double() and possible a weak value for PI.

An improvement is to perform argument reduction in degrees before calling the trig function. The below reduces the angle first to a -45xc2xb0 to 45xc2xb0 range and then calls sin(). This will insure that large values of N in sind(90.0*N) --> -1.0, 0.0, 1.0. . Note: sind(360.0*N +/- 30.0) may not exactly equal +/-0.5. Some additional considerations needed.

#include <math.h> #include <stdio.h>  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; } 

Output

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 ... 
 
 
   
   
9
 
vote

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

En segundo lugar, a veces no puede obtener los valores exactos cuando se usan sin/cos/tan , etc. Funciones, ya que siempre obtiene los resultados que son los más cercanos a los correctos . En su caso, el valor que obtuvo de sin es el más cercano a cero.

El valor de sin(PI) que se ha diferido de cero solo en el dígito 9th después del punto flotante. 3.5897934739308216e-009 es casi igual a 0.000000004 y eso es casi igual a cero.

 

First of all, a cosine of 180 degrees should be equal to -1, so the result you got is right.

Secondly, you sometimes can't get exact values when using sin/cos/tan etc functions as you always get results that are the closest to the correct ones. In your case, the value you got from sin is the closest to zero.

The value of sin(PI) that you got differs from zero only in the 9th (!) digit after the floating point. 3.5897934739308216e-009 is almost equal to 0.000000004 and that's almost equal to zero.

 
 
 
 
5
 
vote

Tengo el mismo problema que el OP al convertir la aplicación a 64 bits.
Mi solución es usar las nuevas funciones de Math .H __COSPI () y __SINPI ().
El rendimiento es similar (incluso un 1% más rápido) que la cos () y el pecado ().

  //    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);   

de 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.                 */   
 

I have the same problem as the OP when converting app to 64-bit.
My solution is to use the new math.h functions __cospi() and __sinpi().
Performance is similar (even 1% faster) than cos() and 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); 

From 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.                 */ 
 
 
 
 

Relacionados problema

34  Definiciones de SQRT, pecado, cos, polla, etc. en CMATH  ( Definitions of sqrt sin cos pow etc in cmath ) 
¿Existen alguna definición de funciones como sqrt() , String [] RCM2 = {"Keep track of status of RCM:", "Add and activate RCM", "Remove RCM", "Dis...

0  Ingrese la letra F o cualquier letra y counte un patrón de alfabeto como un ABC ABCD ABCDE ABCDEF, pero solo funciona si presiono 0  ( Input the letter f or any letter and cout an alphabet pattern like a abc abcd ab ) 
Sin embargo, no pasa nada cuando ingresa a F It solo funciona cuando se ingresa 0, pero lo quiero, así que cuando presiona, obtienes este AB ABC ABCD ABCDE AB...

11  Error de compilación CMATH al compilar el código anterior de C ++ en VS2010  ( Cmath compilation error when compiling old c code in vs2010 ) 
He heredado algunos archivos C ++ y un makefile acompañado, que estoy tratando de traer a VS2010 como una solución. He creado un proyecto vacío y agregué los ...

1  ¿Dónde encontrar el archivo CMATH estándar de C ++ 17?  ( Where to find standard c17 cmath file ) 
¿Dónde puedo encontrar el Function call: isValidWord(hammer, {'a': 1, 'h': 1, 'r': 1, 'm': 2, 'e': 1}, <edX internal wordList>) Output: True 8 Function cal...

3  Es Visual C ++ STD :: ISfinite () ¡Conformación estándar?  ( Is visual c stdisfinite standard conforming ) 
Tengo una clase de envoltura que tiene un operador de conversión implícito de ponderación simple y ligera a double . Me gusta usarlo ya que usaría un doble...

0  LD: "Referencia indefinida al símbolo 'SQRTF'" Error con G ++ a través de APACHE HNT  ( Ld undefined reference to symbol sqrtf error with g via apache ant ) 
Recientemente, estoy tratando de usar Apache HTV con G ++ 4.8 con WebBrowser2 . Si intenté este código pasó. WebBrowser3 Sin embargo, si escribo: ...

3  cos devuelve valores incorrectos?  ( Cos returns wrong values ) 
Tengo un problema extraño con la función de COS estándar de CMATH / MATH .H. Al parecer, en algunas circunstancias, devuelve un valor incorrecto o simplemente...

-9  ¿Cuándo y por qué usaría ABS en C ++?  ( When and why would i use abs in c ) 
Entonces, estaba mirando un código de código abierto que busca a través de un conjunto de números aleatorios para encontrar el número más cercano a 0. y por a...

-2  Interrupción en el conteo para ambos lados  ( Disruption in the count for both sides ) 
Con este programa, estoy tratando de lograr una salida que se vea algo así a + b + c = 7 xmin = 3 xmax = 8 3 ---- 10 4 ---- 11 5 ---- 12 6 ---- ...

100  ¿Cuándo uso FABS y cuándo es suficiente usar STD :: ABS?  ( When do i use fabs and when is it sufficient to use stdabs ) 
Supongo que MyControls1 y MyControls2 se comportan diferentes cuando se usa MyControls3 . Pero cuando uso solo MyControls4 y MyControls5 , ¿tengo que ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos