Quando deve essere una funzione trigonometrica, con un argomento degree, return -0.0?

9

Nella creazione delle funzioni trigonometriche my_sind(d) , my_cosd(d) , my_tand(d) , che usava un argomento di grado piuttosto che uno radiante e forniva risposte esatte a multipli di 90, ho notato che il risultato era a volte -0.0 piuttosto che 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() e tan() restituiscono in genere lo stesso risultato zero del segno per un dato input zero di segno. È logico che my_sin() debba corrispondere a sin() per tali input.

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

La domanda è : per quale numero intero non_zero_n dovrebbe / potrebbe il risultato restituire sempre -0.0 per my_sind(180*non_zero_n) , my_cosd(180*n + 180) , my_tand(180*non_zero_n) ?

È abbastanza facile codificare in modo che solo f(-0.0) generi -0.0 e sia fatto con esso. Semplice chiedersi se c'è qualche ragione per rendere altro f(x) return -0.0 per qualsiasi altro ( diverso da zero ) x e l'importanza di assicurare quel segno.

Nota: non si tratta del motivo per cui 0.0 vs. -0.0 si verifica. Questo non è il motivo per cui cos(machine_pi/4) non restituisce 0.0 . Né si tratta di come controllare la generazione di 0.0 o -0.0 . La vedo meglio come domanda di design.

    
posta chux 03.11.2014 - 06:13
fonte

3 risposte

3

Il principio di progettazione della "sorpresa minima" suggerisce che guardiamo alle funzionalità precedentemente stabilite per l'orientamento. In questo caso, la funzionalità stabilita più vicina è fornita dalle funzioni sinpi e cospi introdotte in IEEE Std 754-2008 (lo standard IEEE per aritmetica a virgola mobile), sezione 9. Queste funzioni non fanno parte dell'attuale ISO C e ISO C ++, ma sono stati incorporati nelle librerie matematiche di varie piattaforme di programmazione, ad esempio CUDA.

Queste funzioni calcolano sin (πx) e cos (πx), dove la moltiplicazione con π si verifica implicitamente all'interno della funzione. tanpi non è definito, ma si può presupporre che, in base all'equivalenza matematica, possa fornire funzionalità in base a tanpi(x) = sinpi(x) / cospi(x) .

Ora possiamo definire sind(x) = sinpi(x/180) , cosd(x) = cospi(x/180) , tand(x) = tanpi(x/180) in modo intuitivo. La sezione 9.1.2 di IEEE-754 spiega come gestire gli argomenti speciali per sinpi e cospi . In particolare:

sinPi(+n) is +0 and sinPi(−n) is −0 for positive integers n. This implies, under appropriate rounding modes, that sinPi(−x) and −sinPi(x) are the same number (or both NaN) for all x. cosPi(n + ½) is +0 for any integer n when n + ½ is representable.

Lo standard IEEE 754-2008 non fornisce una motivazione per i requisiti citati, tuttavia, una prima bozza degli stati della sezione pertinente:

If the value of the function is zero, the sign of this 0 is best determined by considering the continuous extension of the sign function of the mathematical function.

La lettura dell'archivio 754 Working Group Mail Archive può fornire ulteriori approfondimenti, non ho avuto il tempo di scavare attraverso di essa. Implementando sind() , cosd() e tand() come descritto sopra, arriviamo quindi a questa tabella di casi di esempio:

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
    
risposta data 25.03.2016 - 01:15
fonte
5

sin() and tan() typically return the same sign zero result for a given sign zero input

Potrebbe essere generalmente vero poiché:

  • Velocità / Precisione . Per i doppi abbastanza piccoli, la migliore risposta per sin(x) è x . Cioè, per i numeri più piccoli di circa 1.49e-8 , il doppio più vicino al seno di x è in realtà x stesso (vedi codice sorgente glibc per sin () ).

  • Gestione di casi speciali .

    A few extraordinary arithmetic operations are affected by zero's sign; for example "1/(+0) = +inf" but "1/(-0) = -inf". To retain its usefulness, the sign bit must propagate through certain arithmetic operations according to rules derived from continuity considerations.

    Implementations of elementary transcendental functions like sin(z) and tan(z) and their inverses and hyperbolic analogs, though not specified by the IEEE standards, are expected to follow similar rules. The implementation of sin(z) is expected to reproduce the sign of z as well as its value at z = ±O.

    ( Tagli di diramazione per funzioni elementari complesse o molto rumore del bit di segno di niente di W. Kahan)

    Lo zero negativo firmato fa eco al concetto di analisi matematica dell'approssimazione di 0 dal basso come limite unilaterale (si consideri 1 / sin(x) : il segno di zero fa un'enorme differenza).

Modifica

Considerando il secondo punto vorrei scrivere my_sind in modo che:

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

L'ultimo standard C (F.10.1.6 sin e F.10.1.7 tan , implementazioni con uno zero firmato), specifica che se l'argomento è ±0 , it viene restituito non modificato .

EDIT 2

Per gli altri valori penso che sia una questione di approssimazione. Dato 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

Quindi se my_sind fornisce risposte esatte a multipli di 180 °, può restituire +0.0 o -0.0 (non vedo un chiaro motivo per preferire l'uno rispetto all'altro).

Se my_sind utilizza una qualche approssimazione (ad esempio una formula di conversione degree * M_PI / 180.0 ), dovrebbe considerare in che modo si sta avvicinando ai valori critici.

    
risposta data 03.11.2014 - 12:00
fonte
3

The library doesn't try to distinguish +0 from -0. IEEE 754 worries quite a bit about this distinction...I found the functions [in math.h] quite hard enough to write without fretting about the sign of nothing. -- P.J. Plauger, The Standard C Library, 1992, page 128.

Formalmente, le funzioni trigonometriche dovrebbero restituire il segno di zero in accordo con lo standard C ... che lascia il comportamento indefinito.

Di fronte a un comportamento indefinito, il principio del minimo stupore suggerisce di duplicare il comportamento della funzione corrispondente da math.h . Questo odore è giustificabile, mentre divergono dal comportamento della funzione corrispondente in math.h odori come un modo per introdurre bug nel codice esatto che dipende dal segno dello zero.

    
risposta data 03.11.2014 - 14:43
fonte

Leggi altre domande sui tag