1. 程式人生 > 實用技巧 >fmal (Numerics) – C 中文開發手冊

fmal (Numerics) – C 中文開發手冊

[
  •   C 語言中文開發手冊

    fmal (Numerics) - C 中文開發手冊

    在標頭檔案<math.h>中定義
    float fmaf( float x, float y, float z ); (1) (自C99)
    double fma( double x, double y, double z ); (2) (自 C99)
    long double fmal( long double x, long double y, long double z ); (3) (自C99)
    #define FP_FAST_FMA /* implementation-defined */ (4) (自C99)
    #define FP_FAST_FMAF /* implementation-defined */ (5) (自C99)
    #define FP_FAST_FMAL /* implementation-defined */ (6) (自C99)
    在標頭檔案<tgmath.h>中定義
    #define fma( x, y, z ) (7) (自C99)

    1-3)計算(x * y)+ z,就像無限精度一樣,只舍入一次以適應結果型別。4-6)如果定義了巨集常量FP_FAST_FMAF,FP_FAST_FMA或FP_FAST_FMAL,則相應函式fmaf,fma或fmal的計算速度(除了更精確之外)的計算結果要高於float,double和x * y + z的表示式 長雙重論點,分別。 如果定義,這些巨集評估為整數1。7)型別泛型巨集:如果任何引數的型別為long double,則呼叫fmal。 否則,如果任何引數具有整數型別或型別為double,則呼叫fma。 否則,呼叫fmaf。

    引數

    x, y, z - floating point values

    返回值

    如果成功,則返回(x * y)+ z的值,如同計算為無限精度一樣,並舍入一次以適合結果型別(或者,也可以計算為單個三元浮點運算)。如果發生由溢位引起的範圍錯誤,則返回±HUGE_VAL,±HUGE_VALF或±HUGE_VALL。如果發生由於下溢導致的範圍錯誤,則返回正確的值(舍入後)。

    錯誤處理

    按照math_errhandling中的指定報告錯誤。如果實現支援IEEE浮點運算(IEC 60559),如果x是零並且y是無限的或者如果x是無限的並且y是零並且z不是NaN,則返回NaN並且引發FE_INVALID如果x是零並且y是無限的或者如果x是無限的並且y是零並且z是NaN,則返回NaN並且可以提升FE_INVALID如果x * y是一個精確的無窮大而z是一個具有相反符號的無窮大,則返回NaN並且引發FE_INVALID如果x或y是NaN,則返回NaN如果z是NaN,並且x * y不是0 * Inf或Inf * 0,則返回NaN(不含FE_INVALID)

    注意

    這種操作通常以硬體實現為融合乘加 CPU指令。如果硬體支援,則應該定義適當的FP_FAST_FMA *巨集,但是即使未定義巨集,許多實現也會使用CPU指令。POSIX指定值x * y無效且z是NaN的情況為:域錯誤。由於其無限的中間精度,fma是其他正確舍入的數學運算的常見構建模組,例如sqrt或甚至除CPU之外的分割槽(例如Itanium)。與所有浮點表示式一樣,除非#pragma STDC FP_CONTRACT處於關閉狀態,否則表示式(x * y)+ z可能會編譯為已融合的多重加法。

    #include <stdio.h>
    #include <math.h>
    #include <float.h>
    #include <fenv.h>
    #pragma STDC FENV_ACCESS ON
    int main(void)
    {
        // demo the difference between fma and built-in operators
        double in = 0.1;
        printf("0.1 double is %.23f (%a)\n", in, in);
        printf("0.1*10 is 1.0000000000000000555112 (0x8.0000000000002p-3),"
               " or 1.0 if rounded to double\n");
        double expr_result = 0.1 * 10 - 1;
        printf("0.1 * 10 - 1 = %g : 1 subtracted after "
               "intermediate rounding to 1.0\n", expr_result);
        double fma_result = fma(0.1, 10, -1);
        printf("fma(0.1, 10, -1) = %g (%a)\n", fma_result, fma_result);
     
        // fma use in double-double arithmetic
        printf("\nin double-double arithmetic, 0.1 * 10 is representable as ");
        double high = 0.1 * 10;
        double low = fma(0.1, 10, -high);
        printf("%g + %g\n\n", high, low);
     
        //error handling
        feclearexcept(FE_ALL_EXCEPT);
        printf("fma(+Inf, 10, -Inf) = %f\n", fma(INFINITY, 10, -INFINITY));
        if(fetestexcept(FE_INVALID)) puts("    FE_INVALID raised");
    }

    可能的輸出:

    0.1 double is 0.10000000000000000555112 (0x1.999999999999ap-4)
    0.1*10 is 1.0000000000000000555112 (0x8.0000000000002p-3), or 1.0 if rounded to double
    0.1 * 10 - 1 = 0 : 1 subtracted after intermediate rounding to 1.0
    fma(0.1, 10, -1) = 5.55112e-17 (0x1p-54)
     
    in double-double arithmetic, 0.1 * 10 is representable as 1 + 5.55112e-17
     
    fma(+Inf, 10, -Inf) = -nan
        FE_INVALID raised

    參考

    C11標準(ISO / IEC 9899:2011): 7.12.13.1 fma函式(p:258) 7.25型別通用數學<tgmath.h>(p:373-375) F.10.10.1 fma函式(p:530) C99標準(ISO / IEC 9899:1999): 7.12.13.1 fma函式(p:239) 7.22型別通用數學<tgmath.h>(p:335-337) F.9.10.1 fma函式(p:466)

    擴充套件內容

    remainderremainderfremainderl (C99)(C99)(C99) 計算浮點除法運算的有符號餘數(函式)
    remquoremquofremquol(C99)(C99)(C99) 計算帶符號的餘數以及除法操作(函式)的最後三位

    | fma的C ++文件 |

  •   C 語言中文開發手冊
    ]
  •   本文標題:fmal (Numerics) – C 中文開發手冊 - Break易站轉載請保留頁面地址:https://www.breakyizhan.com/c-3/27335.html