我认为 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 中的一个错误(我怀疑它会是......)?