Namespaces
Variants

std:: remquo, std:: remquof, std:: remquol

From cppreference.net
Common mathematical functions
Nearest integer floating point operations
(C++11)
(C++11)
(C++11) (C++11) (C++11)
Floating point manipulation functions
(C++11) (C++11)
(C++11)
(C++11)
Classification and comparison
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Types
(C++11)
(C++11)
(C++11)
Macro constants
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 ) ;

long double remquo ( long double x, long double y, int * quo ) ;
(depuis C++11)
(jusqu'à C++23)
constexpr /* floating-point-type */

remquo ( /* floating-point-type */ x,

/* floating-point-type */ y, int * quo ) ;
(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 */

remquo ( Arithmetic1 x, Arithmetic2 y, int * quo ) ;
(A) (depuis C++11)
(constexpr depuis C++23)
1-3) Calcule le reste en virgule flottante de l'opération de division x / y comme le fait la fonction std::remainder() . De plus, le signe et au moins les trois derniers bits de x / y seront stockés dans quo , suffisants pour déterminer l'octant du résultat dans une période. La bibliothèque fournit des surcharges de std::remquo pour tous les types en virgule flottante non qualifiés cv comme type des paramètres x et y . (depuis C++23)
A) Des surcharges supplémentaires sont fournies pour toutes les autres combinaisons de types arithmétiques.

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 :

  • Si num1 ou num2 a le type long double , alors std :: remquo ( num1, num2, quo ) a le même effet que std :: remquo ( static_cast < long double > ( num1 ) ,
    static_cast < long double > ( num2 ) , quo )
    .
  • Sinon, si num1 et/ou num2 a le type double ou un type entier, alors std :: remquo ( num1, num2, quo ) a le même effet que std :: remquo ( static_cast < double > ( num1 ) ,
    static_cast < double > ( num2 ) , quo )
    .
  • Sinon, si num1 ou num2 a le type float , alors std :: remquo ( num1, num2, quo ) a le même effet que std :: remquo ( static_cast < float > ( num1 ) ,
    static_cast < float > ( num2 ) , quo )
    .
(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 ) ,
static_cast < /*common-floating-point-type*/ > ( num2 ) , quo )
, où /*common-floating-point-type*/ est le type à virgule flottante ayant le plus grand rang de conversion en virgule flottante et la plus grande sous-catégorie de conversion en virgule flottante entre les types de num1 et num2 , les arguments de type entier sont considérés comme ayant le même rang de conversion en virgule flottante que double .

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

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