sirve sintaxis resueltos que principiantes para lenguaje funciones ejercicios ejemplos codigos caracteristicas c++ precision trigonometry

sintaxis - el resultado sinusoidal depende del compilador C++ utilizado



para que sirve c++ (3)

Uso los dos siguientes compiladores de C ++:

  • cl.exe : Microsoft (R) C / C ++ Optimizing Compiler versión 19.00.24210 para x86
  • g ++ : g ++ (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010

Cuando uso la función sinusoidal integrada, obtengo resultados diferentes. Esto no es crítico, pero a veces los resultados son demasiado significativos para mi uso. Aquí hay un ejemplo con un valor ''hard-coded'':

printf("%f/n", sin(5451939907183506432.0));

Resultado con cl.exe:

0.528463

Resultado con g ++:

0.522491

Sé que el resultado de g ++ es más preciso y que podría usar una biblioteca adicional para obtener el mismo resultado, pero ese no es mi punto aquí. Realmente entendería lo que sucede aquí: ¿por qué está cl.exe tan mal?

Algo gracioso, si aplico un módulo de (2 * pi) en el param, entonces obtengo el mismo resultado que g ++ ...

[EDIT] Solo porque mi ejemplo parece loco para algunos de ustedes: esto es parte de un generador de números pseudoaleatorio. No es importante saber si el resultado del seno es exacto o no: solo necesitamos que dé algún resultado.


Creo que el comentario de Sam es el más cercano a la marca. Mientras está usando una versión reciente de GCC / glibc, que implementa sin () en el software (calculado en tiempo de compilación para el literal en cuestión), cl.exe para x86 probablemente usa la instrucción fsin. Este último puede ser muy impreciso, como se describe en la publicación de blog Random ASCII, " Intel subestima límites de error en 1,3 quintillones ".

Parte del problema con su ejemplo en particular es que Intel usa una aproximación imprecisa de pi al hacer la reducción de rango:

Al hacer la reducción de rango de doble precisión (mantisa de 53 bits) pi, los resultados tendrán aproximadamente 13 bits de precisión (66 menos 53), para un error de hasta 2 ^ 40 ULP (53 menos 13).


De acuerdo con cppreference :

El resultado puede tener poca o ninguna importancia si la magnitud de arg es grande (hasta C ++ 11)

Es posible que esta sea la causa del problema, en cuyo caso querrá hacer manualmente el módulo para que arg no sea grande.


Tienes un literal de 19 dígitos, pero el doble generalmente tiene una precisión de 15-17 dígitos. Como resultado, puede obtener un pequeño error relativo (al convertir al doble), pero lo suficientemente grande (en el contexto del cálculo de seno) error absoluto.

En realidad, las diferentes implementaciones de la biblioteca estándar tienen diferencias en el tratamiento de tales números grandes. Por ejemplo, en mi entorno, si ejecutamos

std::cout << std::fixed << 5451939907183506432.0;

el resultado de g ++ sería 5451939907183506432.000000
cl resultado sería 5451939907183506400.000000

La diferencia se debe a que las versiones de cl anteriores a 19 tienen un algoritmo de formateo que usa solo un número limitado de dígitos y llena los lugares decimales restantes con cero.

Además, veamos este código:

double a[1000]; for (int i = 0; i < 1000; ++i) { a[i] = sin(5451939907183506432.0); } double d = sin(5451939907183506432.0); cout << a[500] << endl; cout << d << endl;

Cuando se ejecuta con mi compilador x86 VC ++, la salida es:

0.522491 0.528463

Parece que al llenar el conjunto, sin se compila a la llamada de __vdecl_sin2 , y cuando hay una sola operación, se compila a la llamada de __libm_sse2_sin_precise (con /fp:precise ).

En mi opinión, su número es demasiado grande para que el cálculo del sin espere el mismo comportamiento de diferentes compiladores y espere el comportamiento correcto en general.