std::nextafter, std::nextafterf, std::nextafterl, std::nexttoward, std::nexttowardf, std::nexttowardl
| Definido en el archivo de encabezado |
||
|
|
(1) | (desde C++11) (constexpr since C++23) |
|
|
(2) | (desde C++11) (constexpr since C++23) |
|
|
(3) | (desde C++11) (constexpr since C++23) |
|
|
(4) | (desde C++11) (constexpr since C++23) |
|
|
(5) | (desde C++11) (constexpr since C++23) |
|
|
(6) | (desde C++11) (constexpr since C++23) |
|
|
(7) | (desde C++11) (constexpr since C++23) |
|
|
(8) | (desde C++11) (constexpr since C++23) |
|
|
(9) | (desde C++11) (constexpr since C++23) |
|
|
(10) | (desde C++11) (constexpr since C++23) |
|
|
(11) | (desde C++11) (constexpr since C++23) |
|
|
(12) | (desde C++11) (constexpr since C++23) |
Devuelve el siguiente valor representable de from en la dirección de to.
1-5) Si from es igual a to, to.
7-11) Si 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.
6) Un conjunto de sobrecargas o una plantilla de función para todas las combinaciones de los argumentos de tipo aritmético no cubiertas por (1-5). Si algún argumento tiene tipo entero, se convierte en 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.
12) Un conjunto de sobrecargas o una plantilla de función que acepta el argumento 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