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?
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?
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 interoi
in modo tale che, sey
è diverso da zero, il risultato ha lo stesso segno comex
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
oy
èNaN
, unNaN
sono consegnatiSe
y
è zero, si verifica un errore di dominio, e di unNaN
(se supportato), o un valore definito dall'implementazione saranno restituiti.Se
x
è infinito, si verificherà un errore di dominio e verrà restituito un valoreNaN
(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
, doven
è il quoziente dinumerator
diviso perdenominator
, arrotondato a zero in un numero intero. Pertanto,fmod
(6.5, 2.3) restituisce 1.9, ovvero 6.5 meno 4.6.
E 'stato probabilmente destinato a comportarsi esattamente come 'fmod', ma è caduto preda di una delle le più comuni insidie nell'arrotondamento. – SirGuy
@jaggedSpire - oops. Sì, giusto. Come 'trunc()' - risolto. – abligh
@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
Si consiglia di leggere questo: http://en.cppreference.com/w/cpp/numeric/math/fmod – NathanOliver