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
Definido en el encabezado <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 ) ;
(desde C++11)
(hasta C++23)
constexpr /* floating-point-type */

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

/* floating-point-type */ y, int * quo ) ;
(desde C++23)
float remquof ( float x, float y, int * quo ) ;
(2) (desde C++11)
(constexpr desde C++23)
long double remquol ( long double x, long double y, int * quo ) ;
(3) (desde C++11)
(constexpr desde C++23)
Definido en el encabezado <cmath>
template < class Arithmetic1, class Arithmetic2 >

/* common-floating-point-type */

remquo ( Arithmetic1 x, Arithmetic2 y, int * quo ) ;
(A) (desde C++11)
(constexpr desde C++23)
1-3) Calcula el resto en punto flotante de la operación de división x / y como lo hace la función std::remainder() . Adicionalmente, el signo y al menos los tres últimos bits de x / y se almacenarán en quo , suficiente para determinar el octante del resultado dentro de un período. La biblioteca proporciona sobrecargas de std::remquo para todos los tipos de punto flotante sin calificación cv como tipo de los parámetros x y y . (since C++23)
A) Se proporcionan sobrecargas adicionales para todas las demás combinaciones de tipos aritméticos.

Contenidos

Parámetros

x, y - valores de punto flotante o enteros
quo - puntero a int para almacenar el signo y algunos bits de x / y

Valor de retorno

Si tiene éxito, retorna el resto en punto flotante de la división x / y como está definido en std::remainder , y almacena, en * quo , el signo y al menos tres de los bits menos significativos de x / y (formalmente, almacena un valor cuyo signo es el signo de x / y y cuya magnitud es congruente módulo 2 n
con la magnitud del cociente integral de x / y , donde n es un entero definido por la implementación mayor o igual a 3 ).

Si y es cero, el valor almacenado en * quo no está especificado.

Si ocurre un error de dominio, se devuelve un valor definido por la implementación (NaN donde esté soportado).

Si ocurre un error de rango debido a desbordamiento inferior, se devuelve el resultado correcto si se admiten subnormales.

Si y es cero, pero no se produce el error de dominio, se devuelve cero.

Manejo de errores

Los errores se reportan como se especifica en math_errhandling .

Puede ocurrir un error de dominio si y es cero.

Si la implementación soporta aritmética de punto flotante IEEE (IEC 60559),

  • El modo de redondeo actual rounding mode no tiene efecto.
  • FE_INEXACT nunca se activa.
  • Si x es ±∞ y y no es NaN, se retorna NaN y se activa FE_INVALID .
  • Si y es ±0 y x no es NaN, se retorna NaN y se activa FE_INVALID .
  • Si cualquiera x o y es NaN, se retorna NaN.

Notas

POSIX requiere que ocurra un error de dominio si x es infinito o y es cero.

Esta función es útil al implementar funciones periódicas con el período exactamente representable como un valor de punto flotante: al calcular sin(πx) para un x muy grande, llamar std::sin directamente puede resultar en un gran error, pero si el argumento de la función se reduce primero con std::remquo , los bits de bajo orden del cociente pueden usarse para determinar el signo y el octante del resultado dentro del período, mientras que el resto puede usarse para calcular el valor con alta precisión.

En algunas plataformas esta operación es soportada por hardware (y, por ejemplo, en CPUs Intel, FPREM1 deja exactamente 3 bits de precisión en el cociente cuando se completa).

Las sobrecargas adicionales no requieren ser proporcionadas exactamente como (A) . Solo necesitan ser suficientes para garantizar que para su primer argumento num1 y segundo argumento num2 :

  • Si num1 o num2 tiene tipo long double , entonces std :: remquo ( num1, num2, quo ) tiene el mismo efecto que std :: remquo ( static_cast < long double > ( num1 ) ,
    static_cast < long double > ( num2 ) , quo )
    .
  • En caso contrario, si num1 y/o num2 tiene tipo double o un tipo entero, entonces std :: remquo ( num1, num2, quo ) tiene el mismo efecto que std :: remquo ( static_cast < double > ( num1 ) ,
    static_cast < double > ( num2 ) , quo )
    .
  • En caso contrario, si num1 o num2 tiene tipo float , entonces std :: remquo ( num1, num2, quo ) tiene el mismo efecto que std :: remquo ( static_cast < float > ( num1 ) ,
    static_cast < float > ( num2 ) , quo )
    .
(hasta C++23)

Si num1 y num2 tienen tipos aritméticos, entonces std :: remquo ( num1, num2, quo ) tiene el mismo efecto que std :: remquo ( static_cast < /*common-floating-point-type*/ > ( num1 ) ,
static_cast < /*common-floating-point-type*/ > ( num2 ) , quo )
, donde /*common-floating-point-type*/ es el tipo de punto flotante con el mayor rango de conversión de punto flotante y mayor subrango de conversión de punto flotante entre los tipos de num1 y num2 , los argumentos de tipo entero se consideran con el mismo rango de conversión de punto flotante que double .

Si no existe tal tipo de punto flotante con el mayor rango y subrango, entonces la resolución de sobrecarga no resulta en un candidato utilizable de las sobrecargas proporcionadas.

(desde C++23)

Ejemplo

#include <cfenv>
#include <cmath>
#include <iostream>
#ifndef __GNUC__
#pragma STDC FENV_ACCESS ON
#endif
const double pi = std::acos(-1); // o std::numbers::pi desde C++20
double cos_pi_x_naive(double x)
{
    return std::cos(pi * x);
}
// el período es 2, los valores son (0;0.5) positivos, (0.5;1.5) negativos, (1.5,2) positivos
double cos_pi_x_smart(double x)
{
    int quadrant;
    double rem = std::remquo(x, 1, &quadrant);
    quadrant = static_cast<unsigned>(quadrant) % 2; // El período es 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';
    // manejo de errores
    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 activado\n";
}

Salida posible:

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 activado

Véase también

calcula el cociente y el resto de la división entera
(función)
(C++11) (C++11)
resto de la operación de división de punto flotante
(función)
(C++11) (C++11) (C++11)
resto con signo de la operación de división
(función)
Documentación C para remquo