名稱空間
變體
操作

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

來自 cppreference.com
< cpp‎ | 數值‎ | 數學
 
 
 
常用數學函式
函式
基本操作
(C++11)  
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)(C++11)(C++11)
指數函式
(C++11)
(C++11)

(C++11)
(C++11)
冪函式
(C++11)
(C++11)
三角
雙曲函式
(C++11)
(C++11)
(C++11)

誤差函式和伽馬函式
(C++11)
(C++11)
(C++11)
(C++11)
取整浮點運算
(C++11)(C++11)(C++11)
(C++11)
(C++11)
(C++11)(C++11)(C++11)
浮點操縱函式
(C++11)(C++11)
(C++11)
(C++11)
nextafternexttoward
(C++11)(C++11)
(C++11)
分類和比較
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
型別
(C++11)
(C++11)
(C++11)
宏常量
分類
(C++11)(C++11)(C++11)(C++11)(C++11)


 
定義於標頭檔案 <cmath>
(1)
float       nextafter ( float from, float to );

double      nextafter ( double from, double to );

long double nextafter ( long double from, long double to );
(C++11 起)
(直至 C++23)
constexpr /* 浮點型別 */

            nextafter ( /* 浮點型別 */ from,

                        /* 浮點型別 */ to );
(C++23 起)
float       nextafterf( float from, float to );
(2) (C++11 起)
(C++23 起為 constexpr)
long double nextafterl( long double from, long double to );
(3) (C++11 起)
(C++23 起為 constexpr)
(4)
float       nexttoward ( float from, long double to );

double      nexttoward ( double from, long double to );

long double nexttoward ( long double from, long double to );
(C++11 起)
(直至 C++23)
constexpr /* 浮點型別 */

            nexttoward ( /* 浮點型別 */ from,

                         long double to );
(C++23 起)
float       nexttowardf( float from, long double to );
(5) (C++11 起)
(C++23 起為 constexpr)
long double nexttowardl( long double from, long double to );
(6) (C++11 起)
(C++23 起為 constexpr)
定義於標頭檔案 <cmath>
template< class Arithmetic1, class Arithmetic2 >

/* 通用浮點型別 */

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

返回從 fromto 方向的下一個可表示值。

1-3) 如果 from 等於 to,則返回 to 庫為所有 cv 非限定浮點型別提供了 std::nextafter 的過載作為引數 fromto 的型別。(C++23 起)
4-6) 如果 from 等於 to,則返回 to,它從 long double 轉換為函式的返回型別,且不損失範圍或精度。

庫為所有 cv 非限定浮點型別提供了 std::nexttoward 的過載作為引數 from 的型別。然而,如果與 from 對應的引數具有擴充套件浮點型別,則 std::nexttoward 的呼叫是格式錯誤的,因為下一個可表示值(或 to)不保證可表示為 long double

(C++23 起)
A) 為所有其他算術型別組合提供了額外的 std::nextafter 過載。
B) 為所有整數型別提供了額外的 std::nexttoward 過載,這些型別被視為 double

目錄

[編輯] 引數

from, to - 浮點數或整數值

[編輯] 返回值

如果未發生錯誤,則返回從 fromto 方向的下一個可表示值。如果 from 等於 to,則返回 to

如果由於溢位導致範圍錯誤,則返回 ±HUGE_VAL±HUGE_VALF±HUGE_VALL(與 from 具有相同的符號)。

如果由於下溢導致範圍錯誤,則返回正確結果。

[編輯] 錯誤處理

錯誤按 math_errhandling 指定的方式報告。

如果實現支援 IEEE 浮點運算 (IEC 60559),

  • 如果 from 是有限的,但預期結果是無窮大,則引發 FE_INEXACTFE_OVERFLOW
  • 如果 from 不等於 to 且結果是次正規數或零,則引發 FE_INEXACTFE_UNDERFLOW
  • 在任何情況下,返回值都與當前舍入模式無關。
  • 如果 fromto 是 NaN,則返回 NaN。

[編輯] 注意

POSIX 規定溢位和下溢條件是範圍錯誤(errno 可能被設定)。

IEC 60559 建議在 from == to 時返回 from。這些函式改為返回 to,這使得零附近的行為保持一致:std::nextafter(-0.0, +0.0) 返回 +0.0,而 std::nextafter(+0.0, -0.0) 返回 -0.0

std::nextafter 通常透過操作 IEEE 表示來實現(glibc, musl)。

不要求額外提供與 (A) 完全相同的 std::nextafter 過載。它們只需足以確保對於它們的第一個引數 num1 和第二個引數 num2

  • 如果 num1num2 的型別是 long double,則 std::nextafter(num1, num2) 的效果與 std::nextafter(static_cast<long double>(num1),
                   static_cast<long double>(num2))
    相同。
  • 否則,如果 num1 和/或 num2 的型別是 double 或整數型別,則 std::nextafter(num1, num2) 的效果與 std::nextafter(static_cast<double>(num1),
                   static_cast<double>(num2))
    相同。
  • 否則,如果 num1num2 的型別是 float,則 std::nextafter(num1, num2) 的效果與 std::nextafter(static_cast<float>(num1),
                   static_cast<float>(num2))
    相同。
(直至 C++23)

如果 num1num2 具有算術型別,則 std::nextafter(num1, num2) 的效果與 std::nextafter(static_cast</*common-floating-point-type*/>(num1),
               static_cast</*common-floating-point-type*/>(num2))
相同,其中 /*common-floating-point-type*/num1num2 的型別中具有最高浮點轉換等級和最高浮點轉換子等級的浮點型別,整數型別引數被視為與 double 具有相同的浮點轉換等級。

如果不存在具有最高等級和次等級的浮點型別,則過載決議不會從提供的過載中產生可用的候選函式。

(C++23 起)

不要求額外提供與 (B) 完全相同的 std::nexttoward 過載。它們只需足以確保對於其整數型別的引數 numstd::nexttoward(num) 的效果與 std::nexttoward(static_cast<double>(num)) 相同。

[編輯] 示例

#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);
}

輸出

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

[編輯] 參閱

C 文件 關於 nextafter