¿Cuándo debería una función trigonométrica, con un argumento de grado, devolver -0.0?

10

En la creación de funciones trigonométricas my_sind(d), my_cosd(d), my_tand(d), que utiliza un argumento grado más que un un radián y proporcionan respuestas exactas a múltiplos de 90, me di cuenta de que el resultado era a veces -0.0en lugar de 0.0.

my_sind( 0.0) -->  0.0
my_sind(-0.0) --> -0.0

my_sind(180.0) --> -0.0
my_sind(360.0) -->  0.0

sin()y tan()normalmente devuelve el mismo resultado de signo cero para una entrada de signo cero dada. Tiene sentido que my_sin()coincida sin()con esas entradas.

my_sind( 0.0) alike sin( 0.0) -->  0.0
my_sind(-0.0) alike sin(-0.0) --> -0.0

La pregunta es : ¿para qué número entero non_zero_ndebe / puede devolver el resultado nunca -0.0para my_sind(180*non_zero_n), my_cosd(180*n + 180), my_tand(180*non_zero_n)?

Es bastante fácil de codificar, por lo que solo f(-0.0)produce -0.0y termina con él. Simplemente preguntándome si hay alguna razón para hacer otro f(x) retorno -0.0por otro ( distinto de cero ) xy la importancia de asegurar ese signo.


Nota: Esta no es una cuestión de por qué ocurre 0.0vs. -0.0Esto no es por qué cos(machine_pi/4)no regresa 0.0. Tampoco se trata de cómo controlar la generación de 0.0o -0.0. Lo veo mejor como una pregunta de diseño.

chux - Restablece a Monica
fuente

Respuestas:

4

El principio de diseño de "menos sorpresa" sugiere que busquemos orientación en la funcionalidad previamente establecida. En este caso, la funcionalidad establecida más cercana es proporcionada por sinpiy las cospifunciones introducidas en IEEE Std 754-2008 (el Estándar IEEE para Aritmética de punto flotante), sección 9. Estas funciones no son parte de los estándares ISO C e ISO C ++ actuales, pero se han incorporado a las bibliotecas matemáticas de varias plataformas de programación, por ejemplo, CUDA.

Estas funciones calculan sen (πx) y cos (πx), donde la multiplicación con π ocurre implícitamente dentro de la función. tanpino está definido, pero podría, en base a la equivalencia matemática, suponerse que proporciona funcionalidad de acuerdo con tanpi(x) = sinpi(x) / cospi(x).

Ahora podemos definir sind(x) = sinpi(x/180), cosd(x) = cospi(x/180), tand(x) = tanpi(x/180)de una manera intuitiva. La Sección 9.1.2 de IEEE-754 explica el manejo de argumentos especiales para sinpiy cospi. En particular:

sinPi (+ n) es +0 y sinPi (−n) es −0 para enteros positivos n. Esto implica, bajo los modos de redondeo apropiados, que sinPi (−x) y −sinPi (x) son el mismo número (o ambos NaN) para todas las x. cosPi (n + ½) es +0 para cualquier número entero n cuando n + ½ es representable.

El estándar IEEE 754-2008 no da una justificación para los requisitos citados, sin embargo, un borrador inicial de la sección relevante establece:

Si el valor de la función es cero, el signo de este 0 se determina mejor considerando la extensión continua de la función de signo de la función matemática.

La lectura del 754 Working Group Mail Archive puede proporcionar información adicional, no he tenido tiempo de investigarlo. Implementando sind(), cosd()y tand()como se describió anteriormente, llegamos a esta tabla de casos de ejemplo:

SIND
 angle value 
  -540 -0
  -360 -0
  -180 -0
     0  0
   180  0
   360  0
   540  0

COSD
 angle value
  -630  0
  -450  0
  -270  0
   -90  0
    90  0
   270  0
   450  0

TAND
 angle value
  -540  0
  -360 -0
  -180  0
     0  0
   180 -0
   360  0
   540 -0
njuffa
fuente
5

sin () y tan () generalmente devuelven el mismo resultado de signo cero para una entrada de signo cero dada

En general, podría ser cierto ya que:

  • Velocidad / precisión . Para dobles lo suficientemente pequeños, la mejor respuesta sin(x)es x. Es decir, para números más pequeños que aproximadamente 1.49e-8, el doble más cercano al seno de x es en realidad x en sí mismo (consulte el código fuente de glibc para sin () ).

  • Manejo de casos especiales .

    Algunas operaciones aritméticas extraordinarias se ven afectadas por el signo de cero; por ejemplo "1/(+0) = +inf"pero "1/(-0) = -inf". Para conservar su utilidad, el bit de signo debe propagarse a través de ciertas operaciones aritméticas de acuerdo con reglas derivadas de consideraciones de continuidad.

    Se espera que las implementaciones de funciones trascendentales elementales como sin (z) y tan (z) y sus inversas y análogos hiperbólicos, aunque no estén especificadas por los estándares IEEE, sigan reglas similares. Se sin(z) espera que lazz = ±O implementación de reproduzca tanto el signo como su valor en .

    ( Cortes de rama para funciones elementales complejas o mucho ruido y pocas nueces por W. Kahan)

    El cero con signo negativo refleja el concepto de análisis matemático de acercarse a 0 desde abajo como un límite unilateral (considere 1 / sin(x): el signo de cero hace una gran diferencia).

EDITAR

Considerando el segundo punto, escribiría my_sindpara que:

my_sind(-0.0) is -0.0
my_sind(0.0) is 0.0

El último estándar C (F.10.1.6 siny F.10.1.7 tan, implementaciones con un cero con signo), especifica que si el argumento es ±0, se devuelve sin modificar .

EDITAR 2

Para los otros valores, creo que es una cuestión de aproximación. Dado M_PI<π:

0 = sin(π) < sin(M_PI)  1.2246467991473532e-16  +0.0
0 = sin(-π) > sin(-M_PI)  -1.2246467991473532e-16  -0.0
0 = sin(2*π) > sin(2*M_PI)  -2.4492935982947064e-16
0 = sin(-2*π) < sin(-2*M_PI)  2.4492935982947064e-16

Entonces, si my_sindproporciona respuestas exactas en múltiplos de 180 °, puede regresar +0.0o -0.0(no veo una razón clara para preferir una sobre la otra).

Si my_sindusa alguna aproximación (por ejemplo, una degree * M_PI / 180.0fórmula de conversión), debe considerar cómo se está acercando a los valores críticos.

manlio
fuente
¿A qué se refieren sus pensamientos sind(180), sind(-180), sind(360), sind(-360),...?
chux - Restablece a Mónica el
Gracias por la actualización. Tal vez mi publicación no está clara. La pregunta principal es si my_trig(x)alguna vez debería volver -0.0cuando |x|no 0.0.
chux - Restablece a Mónica el
Gracias por el "Entonces, si my_sind proporciona respuestas exactas en múltiplos de 180 °, puede devolver +0.0 o -0.0 (no veo una razón clara para preferir una sobre la otra)". Es el punto de discusión más cercano hasta ahora. Estoy pensando que el "principio del mínimo asombro" alienta siempre a regresar +0.0, pero estoy buscando para ver si hay razones de peso para regresar -0.0en algunas situaciones (que no sean x == +/-0.0).
chux - Restablece a Mónica el
@chux: Creo que para múltiplos de 180.0, uno realmente tiene que examinar los valores de precisión relativa de la máquina dados esos valores. Es decir, el incremento / decremento más pequeño que proporciona un valor representable diferente en ese formato numérico. Luego, compare ese valor con el valor verdadero para ver si caería en el lado positivo o negativo.
rwong
@rwong Gracias por la idea. Múltiplos de 90,0 grados , el exactos sind(double degrees) y cosd(double degrees)valor pueden ser devueltos: -1.0, +0.0, +1.0. Esta publicación es acerca de si -0.0alguna vez debe ser devuelta (aparte de sind (-0.0)). Nota: sind()no no utilizar el simple sin(x/360*M_PI)enfoque.
chux - Restablece a Mónica el
3

La biblioteca no intenta distinguir +0 de -0. IEEE 754 se preocupa bastante por esta distinción ... Encontré las funciones [en matemáticas.h] bastante difíciles de escribir sin preocuparse por el signo de nada. - PJ Plauger, The Standard C Library , 1992, página 128.

Formalmente, las funciones trigonométricas deberían devolver el signo de cero de acuerdo con el estándar C ... lo que deja el comportamiento indefinido.

Ante un comportamiento indefinido, el principio de menor asombro sugiere duplicar el comportamiento de la función correspondiente math.h. Esto huele justificable, mientras que diverge del comportamiento de la función correspondiente en math.holores como una forma de introducir errores en el código exactamente que depende del signo de cero.

ben rudgers
fuente
Las funciones trigonométricas en math.hno devuelven 0.0 cuando se dan argumentos como +/- pi / 2 o +/- pi ya que estas funciones solo pueden tomar valores representables cerca de +/- pi / 2, etc. Estos valores "cercanos" devuelven resultados cercanos a 0.0. Dado que las funciones trigonométricas de la biblioteca std ( sin cos tan) no devuelven 0.0 (o -0.0) para ninguna entrada (excepto +/- 0.0), pero my_sind (), my_cosd (), my_tand () pueden devolver 0.0 (o -0.0) no 0.0 comportamiento para duplicar.
chux - Restablece a Mónica el
@chux La premisa que sin(-0.0)debería regresar -0es sospechosa. Trata un detalle de implementación del estándar IEEE como un principio trigonométrico. Aunque hay un principio matemático general de cero como el límite de dos intervalos incorporado en la implementación de IEEE, ocurre en ese nivel de abstracción, no dentro de la trigonometría general [de ahí la variabilidad en lo que devuelven sus funciones trigonométricas]. Lo mejor que puede suceder es que puede definir una convención arbitraria, pero será divergente de la falta de math.hequilibrio sobre el signo de cero.
Ben Rudgers
Nota: no estoy sugiriendo sin(-0.0)que regrese -0.0, pero eso my_sind(x)debería coincidir sin(x)cuando xsea +/-0.0. IOW: siga la práctica previa. Además, la pregunta en sí es más acerca de qué hacer cuando x != 0.0, ¿ my_sind(x)alguna vez debería regresar -0.0como en my_sind(180), etc.? Tal vez su respuesta / comentario aborde eso, pero no lo he visto.
chux - Restablece a Mónica el
@chux Si el comportamiento no está definido, entonces no está definido. Así es exactamente C. Plauger no se preocupó +0frente a -0cuando escribió hace math.hveinte años. No me queda claro qué problema está resolviendo su inquietud por la diferencia.
Ben Rudgers
1
Esperemos que vea que para un bien implementado sin(rad)para cualquier valor rad>0y de cualquier precisión nunca cederá 0.0ya que pi es irracional. [Ref] (www.csee.umbc.edu/~phatak/645/supl/Ng-ArgReduction.pdf) Sin embargo, my_sind(deg)produce un exacto 0.0(ya sea + o -) cada múltiplo de 180.0como el valor 0.0 es el resultado matemático correcto. El "principio del mínimo asombro" sugiere devolver 0.0 en estos casos. Mi pregunta es ¿ -0.0alguna vez debería devolverse en estos casos?
chux - Restablece a Mónica el