Gcc 长双次次正规化/非正规化被截断为0[-Woverflow]

Gcc 长双次次正规化/非正规化被截断为0[-Woverflow],gcc,floating-point,c99,ieee-754,quadruple-precision,Gcc,Floating Point,C99,Ieee 754,Quadruple Precision,在IEEE754standarad中,最小严格正值(低于正常值)为2−16493≈ 10−4965使用四精度浮点格式。为什么GCC拒绝低于10-4949的任何内容?我在寻找一个解释,解释下可能发生的不同事情,这些事情决定了极限是10-4949,而不是10−4965 #包括 void prt_ldbl(长双层车){ 无符号字符*desmond=(无符号字符*)&decker; int i; 对于(i=0;i

IEEE754
standarad中,最小严格正值(低于正常值)为2−16493≈ 10−4965使用四精度浮点格式。为什么GCC拒绝低于10-4949的任何内容?我在寻找一个解释,解释下可能发生的不同事情,这些事情决定了极限是10-4949,而不是10−4965

#包括
void prt_ldbl(长双层车){
无符号字符*desmond=(无符号字符*)&decker;
int i;
对于(i=0;i

我正在使用-不确定它运行在哪个体系结构上(我意识到这可能是罪魁祸首)。请随时发布您在不同体系结构中的发现。

您的
长双精度类型可能不是(*)四倍精度。这可能只是一个简单的问题。这种格式的指数位数与四元精度相同,但有效位要少得多,因此可以表示的最小值听起来差不多正确(2-16445)



(*)您的
长双精度
可能不是四精度,因为没有处理器在硬件中实现四精度。编译器始终可以在软件中实现四精度,但更可能将
长双精度
映射到双精度、扩展双精度或到。

最小的80位
长双精度
约为2-16382-63~=10-4951,而不是2-164934。因此编译器是完全正确的;您的数字小于最小的次正常值。

FWIW
clang
给我提示:
警告:浮点常量的大小对于“long double”类型太小;最小值为3.64519953188247460253E-4951[-Wliteral range]
另一个FWIW:
clang-dM-E-
给出了
#定义#定义#定义#最小值#3.64519953188247460253E-4951L
#定义#最小值#我起初也这么想,但gcc和clang的更高版本似乎支持长双精度128位四精度。现场演示:@PaulR我看过GCC的
\uuu float128
,但它没有映射到
长双精度
。使用它的一个尴尬之处就是,当您想要一个不能准确表示为
double
long double
常量的常量时,必须将字符串传递给函数:当然-但显然gcc和clang都认为
sizeof(long double)==16
现在。@paurr
长双精度的16字节大小并不表示其中有意义的位数。对于将
长双精度
映射到80位扩展双精度的编译器,为了对齐,表示为6/16填充。啊哈-你可能是对的-可能只是80位“隐藏”?有一点我不明白:最小正四精度值是2^−16493年,因为维基百科这么说。最小正扩展双精度值应大2^49倍,因为这种格式有效地减少了49个有效位(6*8+1)。因此,这应该使最小的80位
长双精度
2^-16444,不是吗?MPFR开发人员认为2^-16445:Joseph Myers认为2^-16444:@PascalCuoq:简单的C程序重复将
(长双精度)1
除以2,直到得到zeor并打印出它得到的最后一个非零值,它说答案大约是3.6452e-4951,这是2^(-16382-63)。请记住,80位
长双精度
s没有隐含位。显式前导位是“(6*8+1)”中的“1”。事实证明,维基百科说最小的四精度非规范值是2是错误的^−16493应该是2^-16494。其中一个应该是另一个的2^49倍(现在正在调查GCC源代码中是否存在16444)
#include <stdio.h>

void prt_ldbl(long double decker) {
    unsigned char * desmond = (unsigned char *) & decker;
    int i;

    for (i = 0; i < sizeof (decker); i++) {
         printf ("%02X ", desmond[i]);
    }
    printf ("\n");
}

int main()
{
    long double x = 1e-4955L;
    prt_ldbl(x);
}