std:: remquo, std:: remquof, std:: remquol
|
Défini dans l'en-tête
<cmath>
|
||
| (1) | ||
|
float
remquo
(
float
x,
float
y,
int
*
quo
)
;
double
remquo
(
double
x,
double
y,
int
*
quo
)
;
|
(depuis C++11)
(jusqu'à C++23) |
|
|
constexpr
/* floating-point-type */
remquo
(
/* floating-point-type */
x,
|
(depuis C++23) | |
|
float
remquof
(
float
x,
float
y,
int
*
quo
)
;
|
(2) |
(depuis C++11)
(constexpr depuis C++23) |
|
long
double
remquol
(
long
double
x,
long
double
y,
int
*
quo
)
;
|
(3) |
(depuis C++11)
(constexpr depuis C++23) |
|
Défini dans l'en-tête
<cmath>
|
||
|
template
<
class
Arithmetic1,
class
Arithmetic2
>
/* common-floating-point-type */
|
(A) |
(depuis C++11)
(constexpr depuis C++23) |
std::remquo
pour tous les types en virgule flottante non qualifiés cv comme type des paramètres
x
et
y
.
(depuis C++23)
Table des matières |
Paramètres
| x, y | - | valeurs à virgule flottante ou entières |
| quo | - | pointeur vers int pour stocker le signe et certains bits de x / y |
Valeur de retour
En cas de succès, retourne le reste en virgule flottante de la division
x
/
y
tel que défini dans
std::remainder
, et stocke, dans
*
quo
, le signe et au moins trois des bits de poids faible de
x
/
y
(formellement, stocke une valeur dont le signe est le signe de
x
/
y
et dont la magnitude est congruente
modulo 2
n
à la magnitude du quotient intégral de
x
/
y
, où
n
est un entier défini par l'implémentation supérieur ou égal à
3
).
Si y est nul, la valeur stockée dans * quo n'est pas spécifiée.
Si une erreur de domaine se produit, une valeur définie par l'implémentation est retournée (NaN là où supporté).
Si une erreur de plage se produit en raison d'un dépassement inférieur, le résultat correct est retourné si les nombres sous-normaux sont pris en charge.
Si y est nul, mais que l'erreur de domaine ne se produit pas, zéro est retourné.
Gestion des erreurs
Les erreurs sont signalées comme spécifié dans math_errhandling .
Une erreur de domaine peut survenir si y est nul.
Si l'implémentation prend en charge l'arithmétique à virgule flottante IEEE (IEC 60559),
- Le mode d'arrondi actuel n'a aucun effet.
- FE_INEXACT n'est jamais déclenchée.
- Si x est ±∞ et y n'est pas NaN, NaN est retourné et FE_INVALID est déclenchée.
- Si y est ±0 et x n'est pas NaN, NaN est retourné et FE_INVALID est déclenchée.
- Si soit x soit y est NaN, NaN est retourné.
Notes
POSIX exige qu'une erreur de domaine se produise si x est infini ou si y est zéro.
Cette fonction est utile lors de l'implémentation de fonctions périodiques avec une période exactement représentable comme valeur à virgule flottante : lors du calcul de
sin(πx)
pour un
x
très grand, l'appel direct à
std::sin
peut entraîner une erreur importante, mais si l'argument de la fonction est d'abord réduit avec
std::remquo
, les bits de poids faible du quotient peuvent être utilisés pour déterminer le signe et l'octant du résultat dans la période, tandis que le reste peut être utilisé pour calculer la valeur avec une haute précision.
Sur certaines plateformes, cette opération est prise en charge par le matériel (et, par exemple, sur les processeurs Intel,
FPREM1
laisse exactement 3 bits de précision dans le quotient lorsqu'elle est terminée).
Les surcharges supplémentaires ne sont pas tenues d'être fournies exactement comme (A) . Elles doivent seulement être suffisantes pour garantir que pour leur premier argument num1 et second argument num2 :
|
(jusqu'en C++23) |
|
Si
num1
et
num2
ont des types arithmétiques, alors
std
::
remquo
(
num1, num2, quo
)
a le même effet que
std
::
remquo
(
static_cast
<
/*common-floating-point-type*/
>
(
num1
)
,
Si aucun tel type à virgule flottante avec le plus grand rang et la plus grande sous-catégorie n'existe, alors la résolution de surcharge ne résulte pas en un candidat utilisable parmi les surcharges fournies. |
(depuis C++23) |
Exemple
#include <cfenv> #include <cmath> #include <iostream> #ifndef __GNUC__ #pragma STDC FENV_ACCESS ON #endif const double pi = std::acos(-1); // ou std::numbers::pi depuis C++20 double cos_pi_x_naive(double x) { return std::cos(pi * x); } // la période est 2, les valeurs sont (0;0.5) positives, (0.5;1.5) négatives, (1.5,2) positives double cos_pi_x_smart(double x) { int quadrant; double rem = std::remquo(x, 1, &quadrant); quadrant = static_cast<unsigned>(quadrant) % 2; // La période est 2. return quadrant == 0 ? std::cos(pi * rem) : -std::cos(pi * rem); } int main() { std::cout << std::showpos << "naive:\n" << " cos(pi * 0.25) = " << cos_pi_x_naive(0.25) << '\n' << " cos(pi * 1.25) = " << cos_pi_x_naive(1.25) << '\n' << " cos(pi * 2.25) = " << cos_pi_x_naive(2.25) << '\n' << "smart:\n" << " cos(pi * 0.25) = " << cos_pi_x_smart(0.25) << '\n' << " cos(pi * 1.25) = " << cos_pi_x_smart(1.25) << '\n' << " cos(pi * 2.25) = " << cos_pi_x_smart(2.25) << '\n' << "naive:\n" << " cos(pi * 1000000000000.25) = " << cos_pi_x_naive(1000000000000.25) << '\n' << " cos(pi * 1000000000001.25) = " << cos_pi_x_naive(1000000000001.25) << '\n' << "smart:\n" << " cos(pi * 1000000000000.25) = " << cos_pi_x_smart(1000000000000.25) << '\n' << " cos(pi * 1000000000001.25) = " << cos_pi_x_smart(1000000000001.25) << '\n'; // gestion des erreurs std::feclearexcept(FE_ALL_EXCEPT); int quo; std::cout << "remquo(+Inf, 1) = " << std::remquo(INFINITY, 1, &quo) << '\n'; if (fetestexcept(FE_INVALID)) std::cout << " FE_INVALID levée\n"; }
Sortie possible :
naive: cos(pi * 0.25) = +0.707107 cos(pi * 1.25) = -0.707107 cos(pi * 2.25) = +0.707107 smart: cos(pi * 0.25) = +0.707107 cos(pi * 1.25) = -0.707107 cos(pi * 2.25) = +0.707107 naive: cos(pi * 1000000000000.25) = +0.707123 cos(pi * 1000000000001.25) = -0.707117 smart: cos(pi * 1000000000000.25) = +0.707107 cos(pi * 1000000000001.25) = -0.707107 remquo(+Inf, 1) = -nan FE_INVALID levée
Voir aussi
|
(C++11)
|
calcule le quotient et le reste de la division entière
(fonction) |
|
(C++11)
(C++11)
|
reste de l'opération de division en virgule flottante
(fonction) |
|
(C++11)
(C++11)
(C++11)
|
reste signé de l'opération de division
(fonction) |
|
Documentation C
pour
remquo
|
|