Namensräume
Varianten
Aktionen

std::nextafter, std::nextafterf, std::nextafterl, std::nexttoward, std::nexttowardf, std::nexttowardl

Von cppreference.com
< cpp‎ | numeric‎ | math
 
 
 
 
Definiert in der Header-Datei <cmath>
(1)
float            nextafter( float from, float to );

double          nextafter( double from, double to );

long double      nextafter( long double from, long double to );
(seit C++11)
(bis C++23)
constexpr /* gleitkommazahl-Typ */

                  nextafter( /* Gleitkommazahltyp */ from,

                        /* Gleitkommazahltyp */ to );
(seit C++23)
float            nextafterf( float from, float to );
(2) (seit C++11)
(constexpr seit C++23)
long double      nextafterl( long double from, long double to );
(3) (seit C++11)
(constexpr seit C++23)
(4)
float            nexttoward( float from, long double to );

double          nexttoward( double from, long double to );

long double      nexttoward( long double from, long double to );
(seit C++11)
(bis C++23)
constexpr /* gleitkommazahl-Typ */

                  nexttoward( /* Gleitkommazahltyp */ from,

                         long double to );
(seit C++23)
float            nexttowardf( float from, long double to );
(5) (seit C++11)
(constexpr seit C++23)
long double      nexttowardl( long double from, long double to );
(6) (seit C++11)
(constexpr seit C++23)
Definiert in der Header-Datei <cmath>
template< class Arithmetic1, class Arithmetic2 >

/* common-floating-point-type */

    nextafter( Arithmetic1 from, Arithmetic2 to );
(A) (seit C++11)
(constexpr seit C++23)
template< class Integer >
double nexttoward( Integer from, long double to );
(B) (seit C++11)
(constexpr seit C++23)

Gibt den nächsten darstellbaren Wert von from in Richtung to zurück.

1-3) Wenn from gleich to ist, wird to zurückgegeben. Die Bibliothek stellt Überladungen von std::nextafter für alle cv-unqualifizierten Gleitkommatypen als Typ der Parameter from und to bereit.(seit C++23)
4-6) Wenn from gleich to ist, wird to zurückgegeben, konvertiert von long double in den Rückgabetyp der Funktion ohne Verlust von Reichweite oder Präzision.

Die Bibliothek stellt Überladungen von std::nexttoward für alle cv-unqualifizierten Gleitkommatypen als Typ des Parameters from bereit. Eine Aufrufung von std::nexttoward ist jedoch fehlerhaft, wenn das Argument, das from entspricht, einen erweiterten Gleitkommatyp hat, da der nächste darstellbare Wert (oder to) nicht garantiert als long double darstellbar ist.

(seit C++23)
A) Zusätzliche std::nextafter Überladungen werden für alle anderen Kombinationen von arithmetischen Typen bereitgestellt.
B) Zusätzliche std::nexttoward Überladungen werden für alle Ganzzahltypen bereitgestellt, die als double behandelt werden.

Inhalt

[edit] Parameter

from, to - Gleitkomma- oder Ganzzahlwerte

[edit] Rückgabewert

Wenn keine Fehler auftreten, wird der nächste darstellbare Wert von from in Richtung to zurückgegeben. Wenn from gleich to ist, wird to zurückgegeben.

Wenn ein Bereichsfehler aufgrund von Überlauf auftritt, wird ±HUGE_VAL, ±HUGE_VALF oder ±HUGE_VALL zurückgegeben (mit demselben Vorzeichen wie from).

Wenn ein Bereichsfehler aufgrund von Unterlauf auftritt, wird das korrekte Ergebnis zurückgegeben.

[edit] Fehlerbehandlung

Fehler werden wie in math_errhandling beschrieben gemeldet.

Wenn die Implementierung IEEE-Gleitkomma-Arithmetik (IEC 60559) unterstützt,

  • Wenn from endlich ist, aber das erwartete Ergebnis eine Unendlichkeit ist, werden FE_INEXACT und FE_OVERFLOW ausgelöst.
  • Wenn from nicht gleich to ist und das Ergebnis subnormal oder Null ist, werden FE_INEXACT und FE_UNDERFLOW ausgelöst.
  • In jedem Fall ist der zurückgegebene Wert unabhängig vom aktuellen Rundungsmodus.
  • Wenn entweder from oder to NaN ist, wird NaN zurückgegeben.

[edit] Hinweise

POSIX spezifiziert, dass die Überlauf- und Unterlaufbedingungen Bereichsfehler sind (errno kann gesetzt werden).

IEC 60559 empfiehlt, dass from zurückgegeben wird, wenn from == to. Diese Funktionen geben stattdessen to zurück, was das Verhalten um Null konsistent macht: std::nextafter(-0.0, +0.0) gibt +0.0 zurück und std::nextafter(+0.0, -0.0) gibt -0.0 zurück.

std::nextafter wird typischerweise durch Manipulation der IEEE-Darstellung implementiert (glibc, musl).

Die zusätzlichen std::nextafter Überladungen müssen nicht exakt wie (A) bereitgestellt werden. Sie müssen nur ausreichen, um sicherzustellen, dass für ihr erstes Argument num1 und ihr zweites Argument num2

  • Wenn num1 oder num2 den Typ long double hat, dann hat std::nextafter(num1, num2) denselben Effekt wie std::nextafter(static_cast<long double>(num1),
                   static_cast<long double>(num2))
    .
  • Andernfalls, wenn num1 und/oder num2 den Typ double oder einen Ganzzahltyp haben, dann hat std::nextafter(num1, num2) denselben Effekt wie std::nextafter(static_cast<double>(num1),
                   static_cast<double>(num2))
    .
  • Andernfalls, wenn num1 oder num2 den Typ float hat, dann hat std::nextafter(num1, num2) denselben Effekt wie std::nextafter(static_cast<float>(num1),
                   static_cast<float>(num2))
    .
(bis C++23)

Wenn num1 und num2 arithmetische Typen haben, dann hat std::nextafter(num1, num2) denselben Effekt wie std::nextafter(static_cast</*gemeinsamer-gleitkommazahltyp*/>(num1),
               static_cast</*gemeinsamer-gleitkommazahltyp*/>(num2))
, wobei /*gemeinsamer-gleitkommazahltyp*/ der Gleitkommazahltyp mit dem höchsten Gleitkommakomversionsrang und dem höchsten Gleitkommakomversions-Subrang zwischen den Typen von num1 und num2 ist. Argumente vom Ganzzahltyp werden so behandelt, als hätten sie denselben Gleitkommakomversionsrang wie double.

Wenn kein solcher Gleitkommazahltyp mit dem höchsten Rang und Subrang existiert, dann führt die Überladungsauflösung nicht zu einem nutzbaren Kandidaten aus den bereitgestellten Überladungen.

(seit C++23)

Die zusätzlichen std::nexttoward Überladungen müssen nicht exakt wie (B) bereitgestellt werden. Sie müssen nur ausreichen, um sicherzustellen, dass für ihr Argument num vom Ganzzahltyp, std::nexttoward(num) denselben Effekt hat wie std::nexttoward(static_cast<double>(num)).

[edit] Beispiel

#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 << "The next representable float after " << std::setprecision(20) << from1
              << " is " << to1
              << std::hexfloat << " (" << to1 << ")\n" << std::defaultfloat;
 
    float from2 = 1, to2 = std::nextafter(from2, 2.f);
    std::cout << "The next representable float after " << from2 << " is " << to2
              << std::hexfloat << " (" << to2 << ")\n" << std::defaultfloat;
 
    double from3 = std::nextafter(0.1, 0), to3 = 0.1;
    std::cout << "The number 0.1 lies between two valid doubles:\n"
              << std::setprecision(56) << "    " << from3
              << std::hexfloat << " (" << from3 << ')' << std::defaultfloat
              << "\nand " << to3 << std::hexfloat << "  (" << to3 << ")\n"
              << std::defaultfloat << std::setprecision(20);
 
    std::cout << "\nDifference between nextafter and nexttoward:\n";
    long double dir = std::nextafter(from1, 1.0L); // first subnormal long double
    float x = std::nextafter(from1, dir); // first converts dir to float, giving 0
    std::cout << "With nextafter, next float after " << from1 << " is " << x << '\n';
    x = std::nexttoward(from1, dir);
    std::cout << "With nexttoward, next float after " << from1 << " is " << x << '\n';
 
    std::cout << "\nSpecial values:\n";
    {
        // #pragma STDC FENV_ACCESS ON
        std::feclearexcept(FE_ALL_EXCEPT);
        double from4 = DBL_MAX, to4 = std::nextafter(from4, INFINITY);
        std::cout << "The next representable double after " << std::setprecision(6)
                  << from4 << std::hexfloat << " (" << from4 << ')'
                  << std::defaultfloat << " is " << to4
                  << std::hexfloat << " (" << to4 << ")\n" << std::defaultfloat;
 
        if (std::fetestexcept(FE_OVERFLOW))
            std::cout << "   raised FE_OVERFLOW\n";
        if (std::fetestexcept(FE_INEXACT))
            std::cout << "   raised FE_INEXACT\n";
    } // end FENV_ACCESS block
 
    float from5 = 0.0, to5 = std::nextafter(from5, -0.0);
    std::cout << "std::nextafter(+0.0, -0.0) gives " << 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) gives " << std::fixed << std::setprecision(6) << to
                      << "; Δ = " << Δ << '\n';
    };
 
    precision_loss_demo("\nPrecision loss demo for float:\n", 10.0f);
    precision_loss_demo("\nPrecision loss demo for double:\n", 10.0e9);
    precision_loss_demo("\nPrecision loss demo for long double:\n", 10.0e17L);
}

Ausgabe

The next representable float after 0 is 1.4012984643248170709e-45 (0x1p-149)
The next representable float after 1 is 1.0000001192092895508 (0x1.000002p+0)
The number 0.1 lies between two valid doubles:
    0.09999999999999999167332731531132594682276248931884765625 (0x1.9999999999999p-4)
and 0.1000000000000000055511151231257827021181583404541015625  (0x1.999999999999ap-4)
 
Difference between nextafter and nexttoward:
With nextafter, next float after 0 is 0
With nexttoward, next float after 0 is 1.4012984643248170709e-45
 
Special values:
The next representable double after 1.79769e+308 (0x1.fffffffffffffp+1023) is inf (inf)
   raised FE_OVERFLOW
   raised FE_INEXACT
std::nextafter(+0.0, -0.0) gives -0.000000
 
Precision loss demo for float:
nextafter(1e+01, INF) gives 10.000001; Δ = 0.000001
nextafter(1e+02, INF) gives 100.000008; Δ = 0.000008
nextafter(1e+03, INF) gives 1000.000061; Δ = 0.000061
nextafter(1e+04, INF) gives 10000.000977; Δ = 0.000977
nextafter(1e+05, INF) gives 100000.007812; Δ = 0.007812
nextafter(1e+06, INF) gives 1000000.062500; Δ = 0.062500
nextafter(1e+07, INF) gives 10000001.000000; Δ = 1.000000
nextafter(1e+08, INF) gives 100000008.000000; Δ = 8.000000
 
Precision loss demo for double:
nextafter(1e+10, INF) gives 10000000000.000002; Δ = 0.000002
nextafter(1e+11, INF) gives 100000000000.000015; Δ = 0.000015
nextafter(1e+12, INF) gives 1000000000000.000122; Δ = 0.000122
nextafter(1e+13, INF) gives 10000000000000.001953; Δ = 0.001953
nextafter(1e+14, INF) gives 100000000000000.015625; Δ = 0.015625
nextafter(1e+15, INF) gives 1000000000000000.125000; Δ = 0.125000
nextafter(1e+16, INF) gives 10000000000000002.000000; Δ = 2.000000
 
Precision loss demo for long double:
nextafter(1e+18, INF) gives 1000000000000000000.062500; Δ = 0.062500
nextafter(1e+19, INF) gives 10000000000000000001.000000; Δ = 1.000000
nextafter(1e+20, INF) gives 100000000000000000008.000000; Δ = 8.000000

[edit] Siehe auch

C-Dokumentation für nextafter