2015-11-10 11 views
7

ho scavato nel vecchio codice, e vide una funzione come questa:fmod o non fmod?

inline double mod(double x, double y) 
{ 
    return x-y*floor(x/y); 
} 

è fmod suo equivalente completo, o hanno ho perso qualcosa?

+1

Si consiglia di leggere questo: http://en.cppreference.com/w/cpp/numeric/math/fmod – NathanOliver

risposta

9

No, la routine sopra riportata non è la stessa di fmod(). Nello specifico è diverso per situazioni in cui un argomento è negativo.

La tua routine fa un floor(), che arrotonda al numero intero successivo. Con fmod() l'arrotondamento è come trunc(), vale a dire verso lo zero.

Ecco un estratto del standard Open Group (here):

Queste funzioni devono restituire il valore x- i* y, per qualche intero i in modo tale che, se y è diverso da zero, il risultato ha lo stesso segno come x e grandezza inferiore alla grandezza di .

Se il valore corretto causerebbe underflow e non è rappresentabile, potrebbe verificarsi un errore di intervallo e 0,0 (se supportato) o un valore definito dall'implementazione deve essere restituito.

Se x o y è NaN, un NaN sono consegnati

Se y è zero, si verifica un errore di dominio, e di un NaN (se supportato), o un valore definito dall'implementazione saranno restituiti.

Se x è infinito, si verificherà un errore di dominio e verrà restituito un valore NaN (se supportato) o un valore definito dall'implementazione.

Se x è ±0 e non è zero, è necessario restituire ±0.

Se x non è infinito e y è ±Inf, x deve essere restituito.

Se il valore corretto causerebbe underflow ed è rappresentabile, si può verificare un errore di intervallo e restituire il valore corretto.

che è difficile da capire, ma la parola 'magnitudo' nel primo paragrafo illustra l'arrotondamento è verso lo zero.

Ecco un estratto dalla documentazione molto più utile per la libreria GCC:

Queste funzioni calcolare il resto della divisione di numeratore per il denominatore. Nello specifico, il valore restituito è numerator - n * denominator, dove n è il quoziente di numerator diviso per denominator, arrotondato a zero in un numero intero. Pertanto, fmod (6.5, 2.3) restituisce 1.9, ovvero 6.5 meno 4.6.

+1

E 'stato probabilmente destinato a comportarsi esattamente come 'fmod', ma è caduto preda di una delle le più comuni insidie ​​nell'arrotondamento. – SirGuy

+0

@jaggedSpire - oops. Sì, giusto. Come 'trunc()' - risolto. – abligh

+0

@GuyGreer Perché lo dici? Un sacco di linguaggi/librerie implementano esplicitamente il loro operatore modulo come comportandosi diversamente da c 'fmod' (e seguendo invece la convenzione della funzione OP). Questo è vero per es. Pitone. Questa convenzione effettua anche il test di congruenza (verifica se c'è qualche intero 'k 'tale che' a == b + k * y') * molto * più facile, quindi immagino che sia l'implementazione tipica anche nelle applicazioni di crittografia. – Ponkadoodle