std::nextafter, std::nextafterf, std::nextafterl, std::nexttoward, std::nexttowardf, std::nexttowardl
| Definido en el archivo de encabezado <cmath>
|
||
float nextafter ( float from, float to ); |
(1) | (desde C++11) (constexpr since C++23) |
float nextafterf( float from, float to ); |
(2) | (desde C++11) (constexpr since C++23) |
double nextafter ( double from, double to ); |
(3) | (desde C++11) (constexpr since C++23) |
long double nextafter ( long double from, long double to ); |
(4) | (desde C++11) (constexpr since C++23) |
long double nextafterl( long double from, long double to ); |
(5) | (desde C++11) (constexpr since C++23) |
Promovido nextafter ( Aritmético1 from, Aritmético2 to ); |
(6) | (desde C++11) (constexpr since C++23) |
float nexttoward ( float from, long double to ); |
(7) | (desde C++11) (constexpr since C++23) |
float nexttowardf( float from, long double to ); |
(8) | (desde C++11) (constexpr since C++23) |
double nexttoward ( double from, long double to ); |
(9) | (desde C++11) (constexpr since C++23) |
long double nexttoward ( long double from, long double to ); |
(10) | (desde C++11) (constexpr since C++23) |
long double nexttowardl( long double from, long double to ); |
(11) | (desde C++11) (constexpr since C++23) |
double nexttoward ( TipoEntero from, long double to ); |
(12) | (desde C++11) (constexpr since C++23) |
Devuelve el siguiente valor representable de from en la dirección de to.
from es igual a to, to.from es igual a to, se devuelve to, convertida de long double al tipo de retorno de la función sin pérdida de rango o precisión.double. Si cualquier argumento es long double, entonces el tipo de retorno Promovido también es long double, de lo contrario, el tipo de retorno siempre es double.from de cualquier tipo entero. Equivalente a (9) (el argumento se convierte a double).Parámetros
| from, to | - | Valores de punto flotante. |
Valor de retorno
Si no se producen errores, se devuelve el siguiente valor representable de from en la dirección de to. Si from es igual a to, entonces to.
Si se produce un error de rango debido a desbordamiento, se devuelve HUGE_VAL, ±HUGE_VALF, o ±HUGE_VALL (con el mismo signo que from).
Si se produce un error de rango debido a subdesbordamiento, se devuelve el resultado correcto.
Manejo de errores
Los errores se informan como se especifica en math_errhandling.
Si la implementación admite la aritmética de punto flotante IEEE (IEC 60559):
- Si
fromes finito, pero el resultado esperado es un infinito, genera FE_INEXACT y FE_OVERFLOW. - Si
fromno es igual atoy el resultado es subnormal o cero, genera FE_INEXACT y FE_UNDERFLOW. - En cualquier caso, el valor devuelto es independiente del modo de redondeo actual.
- Si
fromotoes NaN, se devuelve NaN.
Notas
POSIX especifica que las condiciones de desbordamiento y subdesbordamiento son errores de rango (se puede establecer errno).
IEC 60559 recomienda que se devuelva from siempre que from == to. En su lugar, estas funciones devuelven to, lo que hace que el comportamiento alrededor de cero sea consistente: std::nextafter(-0.0, +0.0) devuelve +0.0 y std::nextafter(+0.0, -0.0) devuelve -0.0.
nextafter generalmente se implementa mediante la manipulación de la representación IEEE (glibc, musl).
Ejemplo
#include <cfenv>
#include <cfloat>
#include <cmath>
#include <concepts>
#include <iomanip>
#include <iostream>
int main()
{
float from1 = 0, to1 = std::nextafter(from1, 1.f);
std::cout << "El siguiente float representable después de " << std::setprecision(20) << from1
<< " es " << to1
<< std::hexfloat << " (" << to1 << ")\n" << std::defaultfloat;
float from2 = 1, to2 = std::nextafter(from2, 2.f);
std::cout << "El siguiente float representable después de " << from2 << " es " << to2
<< std::hexfloat << " (" << to2 << ")\n" << std::defaultfloat;
double from3 = std::nextafter(0.1, 0), to3 = 0.1;
std::cout << "El número 0.1 se encuentra entre dos double válidos:\n"
<< std::setprecision(56) << " " << from3
<< std::hexfloat << " (" << from3 << ')' << std::defaultfloat
<< "\ny " << to3 << std::hexfloat << " (" << to3 << ")\n"
<< std::defaultfloat << std::setprecision(20);
std::cout << "\nDiferencia entre nextafter y nexttoward:\n";
long double dir = std::nextafter(from1, 1.0L); // primer long double subnormal
float x = std::nextafter(from1, dir); // primero convierte dir to float, dando 0
std::cout << "Con nextafter, el próximo float después de " << from1 << " es " << x << '\n';
x = std::nexttoward(from1, dir);
std::cout << "Con nexttoward, el próximo float después de " << from1 << " es " << x << '\n';
std::cout << "\nValores especiales:\n";
{
// #pragma STDC FENV_ACCESS ON
std::feclearexcept(FE_ALL_EXCEPT);
double from4 = DBL_MAX, to4 = std::nextafter(from4, INFINITY);
std::cout << "El siguiente double representable después de " << std::setprecision(6)
<< from4 << std::hexfloat << " (" << from4 << ')'
<< std::defaultfloat << " es " << to4
<< std::hexfloat << " (" << to4 << ")\n" << std::defaultfloat;
if(std::fetestexcept(FE_OVERFLOW)) std::cout << " generó FE_OVERFLOW\n";
if(std::fetestexcept(FE_INEXACT)) std::cout << " generó FE_INEXACT\n";
} // fin del bloque FENV_ACCESS
float from5 = 0.0, to5 = std::nextafter(from5, -0.0);
std::cout << "std::nextafter(+0.0, -0.0) da " << std::fixed << to5 << '\n';
auto precision_loss_demo = []<std::floating_point Fp>(const auto rem, const Fp start) {
std::cout << rem;
for (Fp from = start, to, Δ;
(Δ = (to = std::nextafter(from, +INFINITY)) - from) < Fp(10.0);
from *= Fp(10.0))
std::cout << "nextafter(" << std::scientific << std::setprecision(0) << from
<< ", INF) da " << std::fixed << std::setprecision(6) << to
<< "; Δ = " << Δ << '\n';
};
precision_loss_demo("\nDemo de pérdida de precisión para float:\n", 10.0f);
precision_loss_demo("\nDemo de pérdida de precisión para double:\n", 10.0e9);
precision_loss_demo("\nDemo de pérdida de precisión para long double:\n", 10.0e17L);
}
Salida:
El siguiente float representable después de 0 es 1.4012984643248170709e-45 (0x1p-149)
El siguiente float representable después de 1 es 1.0000001192092895508 (0x1.000002p+0)
El número 0.1 se encuentra entre dos double válidos:
0.09999999999999999167332731531132594682276248931884765625 (0x1.9999999999999p-4)
y 0.1000000000000000055511151231257827021181583404541015625 (0x1.999999999999ap-4)
Diferencia entre nextafter y nexttoward:
Con nextafter, el próximo float después de 0 es 0
Con nexttoward, el próximo float después de 0 es 1.4012984643248170709e-45
Valores especiales:
El siguiente double representable después de 1.79769e+308 (0x1.fffffffffffffp+1023) es inf (inf)
generó FE_OVERFLOW
generó FE_INEXACT
std::nextafter(+0.0, -0.0) da -0.000000
Demo de pérdida de precisión para float:
nextafter(1e+01, INF) da 10.000001; Δ = 0.000001
nextafter(1e+02, INF) da 100.000008; Δ = 0.000008
nextafter(1e+03, INF) da 1000.000061; Δ = 0.000061
nextafter(1e+04, INF) da 10000.000977; Δ = 0.000977
nextafter(1e+05, INF) da 100000.007812; Δ = 0.007812
nextafter(1e+06, INF) da 1000000.062500; Δ = 0.062500
nextafter(1e+07, INF) da 10000001.000000; Δ = 1.000000
nextafter(1e+08, INF) da 100000008.000000; Δ = 8.000000
Demo de pérdida de precisión para double:
nextafter(1e+10, INF) da 10000000000.000002; Δ = 0.000002
nextafter(1e+11, INF) da 100000000000.000015; Δ = 0.000015
nextafter(1e+12, INF) da 1000000000000.000122; Δ = 0.000122
nextafter(1e+13, INF) da 10000000000000.001953; Δ = 0.001953
nextafter(1e+14, INF) da 100000000000000.015625; Δ = 0.015625
nextafter(1e+15, INF) da 1000000000000000.125000; Δ = 0.125000
nextafter(1e+16, INF) da 10000000000000002.000000; Δ = 2.000000
Demo de pérdida de precisión para long double:
nextafter(1e+18, INF) da 1000000000000000000.062500; Δ = 0.062500
nextafter(1e+19, INF) da 10000000000000000001.000000; Δ = 1.000000
nextafter(1e+20, INF) da 100000000000000000008.000000; Δ = 8.000000
Véase también
Documentación de C para nextafter
|