gcc13:long double 的精度与 libquadmath 几乎相同;它们都是 80 位浮点实现吗?

问题描述 投票:0回答:0

我认为 GCC 目前(2023 年)将为

long-double
实现 80 位浮点,并为
libquadmath
...

实现 128 位浮点

但是,对于 amd64 架构(AMD FX-8320E)上的 gcc 13.2.0,我发现

long double
__float128
的限制似乎非常接近。并且
LDBL_MAX
FLT128_MAX
都非常接近 x87 80 位标准表示的最大数字(~ 1.18973 x 2^4932)。非规范化最小值恰好是 x87 的
LDBL_TRUE_MIN
(~ 3.6452 x 2^-4951),但对于
FLT_128_DENORM_MIN
它稍大一些 (~ 6.47518 x 2^-4966) 以下程序显示了我的意思:

#include <math.h>
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <quadmath.h>


int main() {
    __float128 qmath_x;

    char *str = malloc(201*sizeof(char));

    /* MAX */
    printf("### MAX ###\n");
    
    printf("LDBL_MAX        %3.190Lg\n", LDBL_MAX);

    qmath_x = FLT128_MAX;
    quadmath_snprintf(str,200,"%3.190Qg",qmath_x);
    printf("FLT128_MAX      %s\n", str);

    if (LDBL_MAX == FLT128_MAX) printf("Yes, they're the same\n");
    else                        printf("No, different!\n");
    
    /* Is max really max? */
    printf("LDBL_MAX*10     %3.190Lg\n", LDBL_MAX * 10);

    qmath_x = FLT128_MAX * 10;
    quadmath_snprintf(str,200,"%3.190Qg",qmath_x);
    printf("FLAT128_MAX*10  %s\n", str);

    
    /* MIN (NORMAL) */
    printf("\n### MIN (NORMAL) ###\n");

    printf("LDBL_MIN    %Lg\n", LDBL_MIN);

    qmath_x = FLT128_MIN;
    quadmath_snprintf(str,200,"%Qg",qmath_x);
    printf("FLAT128_MIN %s\n", str);

    if (LDBL_MIN == FLT128_MIN) printf("Yes, they're the same\n");
    else                        printf("No, different!\n");

    /* MIN (SUBNORMAL) */
    printf("\n### MIN (SUBNORMAL) ###\n");
   
    printf("LDBL_TRUE_MIN        %Lg\n", LDBL_TRUE_MIN);

    qmath_x = FLT128_DENORM_MIN;
    quadmath_snprintf(str,200,"%Qg",qmath_x);
    printf("FLT_128_DENORM_MIN   %s\n", str);

    if (LDBL_TRUE_MIN == FLT128_DENORM_MIN) printf("Yes, they're the same\n");
    else                        printf("No, different!\n");
    
    /* Are these really subnormal minimum? */
    printf("LDBL_TRUE_MIN/2      %Lg\n", LDBL_TRUE_MIN/2);

    qmath_x = FLT128_DENORM_MIN;
    quadmath_snprintf(str,200,"%Qg",qmath_x/2);
    printf("FLT_128_DENORM_MIN/2 %s\n", str);
}

编译:

gcc -Wall -Wextra -O0 long-float-test.c -o long-float-test -lm -lquadmath

输出为:

### MAX ###
LDBL_MAX        1.189731495357231765021263853030970205169063322294624200440323733891737005522970722616410290336528882853545697807495577314427443153670288434198125573853743678673593200706973263201915918282962e+4932
FLT128_MAX      1.189731495357231765085759326628007016196469052641694045529698884212163579755312392324974012848462073525902033564749126859755265433573804462672698751945261490853461958725021262845865799405404e+4932
No, different!
LDBL_MAX*10     inf
FLAT128_MAX*10  inf

### MIN (NORMAL) ###
LDBL_MIN    3.3621e-4932
FLAT128_MIN 3.3621e-4932
Yes, they're the same

### MIN (SUBNORMAL) ###
LDBL_TRUE_MIN        3.6452e-4951
FLT_128_DENORM_MIN   6.47518e-4966
No, different!
LDBL_TRUE_MIN/2      0
FLT_128_DENORM_MIN/2 0

因此,最大表示的数字有点不同(相同的指数,仅在第20个之后有所不同;但是标准化最小值是相同的。现在,非标准化最小值是不同的,即使指数不同) ,但不会太远。

这些只是不同 80 位浮点表示的实现吗?或者四元实际上是 128 位的,而我没有了解其内部结构? (如果是这样,那么它似乎比 x87 80 位更精确,特别接近于零,并且没有那么接近无穷大的优势?)

还是我弄错了——实际上 80 位精度标准和 128 位精度标准之间的差异并没有那么大?我在代码中犯了错误吗?或者甚至,这是 gcc 中的一个错误(我怀疑它会是......)?

gcc precision long-double quadruple-precision
© www.soinside.com 2019 - 2024. All rights reserved.