可以存储在 long double 中的最大整数

Largest integer that can be stored in long double

编辑:在评论中进行了一些讨论后发现,由于幸运地了解如何在 C 中实现浮点数,我问了一些与我想问的不同的问题。
我想使用(进行操作)大于我可以使用 unsigned long long 的整数(对我来说是 8 个字节),可能不会重复出现在数组或 bigint 库中。由于我的 long double 是 16 个字节,我认为只要切换类型就可以实现。事实证明,即使可以表示更大的整数,您也无法在不损失精度的情况下使用这些更大的 long double 整数进行运算。所以不可能实现我想做的事情。实际上,正如评论中所述,这对我来说是不可能的。但总的来说,是否可能取决于你的 long double.

的浮点特性
// end of EDIT

我想了解我可以存储在 long double 中的最大整数是多少。
我知道这取决于程序内置的环境,但我不知道具体如何。我有一个 sizeof(long double) == 16 的价值。

现在 this answer 他们说 64 位双精度数的最大值应该是 2^53,大约是 9 x 10^15,正好是 9007199254740992.
当我 运行 以下程序时,它正常工作:

#include <stdio.h>

int main() {

    long double d = 9007199254740992.0L, i;
    
    printf("%Lf\n", d);
    
    for(i = -3.0; i < 4.0; i++) {
        
        printf("%.Lf) %.1Lf\n", i, d+i);
    }
    
    return 0;
}

它甚至与 11119007199254740992.0L 一起工作,它是在开头添加四个 1 的相同数字。但是,当我再添加一个 1 时,第一个 printf 按预期工作,而所有其他的显示第一个打印的相同数量。
所以我试图用这个程序

获得我的long double的最大值
#include <stdio.h>
#include <math.h>

int main() {

    long double d = 11119007199254740992.0L, i;
    
    for(i = 0.0L; d+i == d+i-1.0; i++) {
        
        if( !fmodl(i, 10000.0L) ) printf("%Lf\n", i);
    }
    
    printf("%.Lf\n", i);
    
    return 0;
}

但它打印 0.
编辑:我刚刚意识到我需要 for 中的条件 !=

总是在同一个答案中,他们说 double 的最大可能值为 DBL_MAX 或大约 1.8 x 10^308。
我不知道这是什么意思,但如果我 运行

printf("%e\n", LDBL_MAX);

我每次都得到一个不同的值,它总是在 6.9 x 10^(-310) 左右。
编辑:我应该使用 %Le,输出值约为 1.19 x 10^4932)
我从 here.

中提取了 LDBL_MAX

这个我也试过了

printf("%d\n", LDBL_MAX_10_EXP);

这给出了值 4932(我也在 C++ 问题中找到了)。

因为我们有 16 个字节用于 long double,即使它们都是类型的整数部分,我们也可以存储数字直到 2^128,即大约 3.4 x 10 ^38。所以我不明白 308、-310 和 4932 应该是什么意思。

有人能告诉我如何找出可以存储为 long double 的最大整数吗?

您可以使用limits.h在您的机器上打印最大值,值为ULLONG_MAX

https://www.geeksforgeeks.org/climits-limits-h-cc/ 中是一个 C++ 示例。

使用 printf() 打印 unsigned long long 的格式说明符是 %llu 打印 long double 它是 %Lf

printf("unsigned long long int: %llu ",(unsigned long long) ULLONG_MAX);

printf("long double: %Lf ",(long double) LDBL_MAX);

https://www.tutorialspoint.com/format-specifiers-in-c

也在Printing unsigned long long int Value Type Returns Strange Results

假设您的意思是“在不丢失信息的情况下存储”,LDBL_MANT_DIG gives the number of bits used for the floating-point mantissa,那么这就是在不丢失信息的情况下可以存储的整数值的位数。*

您需要 128 位整数来轻松确定 128 位浮点数中可以容纳的最大整数值,但这至少会发出十六进制值(假设 unsigned long long 是 64位 - 您可以使用 CHAR_BITsizeof( unsigned long long ) 来获得可移植的答案):

#include <stdio.h>
#include <float.h>
#include <limits.h>


int main( int argc, char **argv )
{
    int tooBig = 0;
    unsigned long long shift = LDBL_MANT_DIG;
    if ( shift >= 64 )
    {
        tooBig = 1;
        shift -= 64;
    }

    unsigned long long max = ( 1ULL << shift ) - 1ULL;

    printf( "Max integer value: 0x" );

    // don't emit an extraneous zero if LDBL_MANT_DIG is
    // exactly 64
    if ( max )
    {
        printf( "%llx", max );
    }

    if ( tooBig )
    {
        printf( "%llx", ULLONG_MAX );
    }

    printf( "\n" );

    return( 0 );
}

* - 迂腐地,它是 FLT_RADIX 基数中的位数,但该基数几乎可以肯定是 2.

鉴于您在评论中表示要使用 long double 代替 long long 以获得更大的范围,我假设您还需要单位精度。因此,您要求的是浮点表示法 (FLT_RADIX) 基数中可用尾数位数 (LDBL_MANT_DIG) 可表示的最大数。在 非常 可能的事件 FLT_RADIX == 2 中,您可以像这样计算该值:

#include <float.h>
#include <math.h>

long double get_max_integer_equivalent() {
    long double max_bit = ldexpl(1, LDBL_MANT_DIG - 1);
    return max_bit + (max_bit - 1);
}

ldexp 系列函数按 2 的幂缩放浮点值,类似于移位运算符(<<>>)对整数所做的操作,因此以上类似于

// not reliable for the purpose!
unsigned long long max_bit = 1ULL << (DBL_MANT_DIG - 1);
return max_bit + (max_bit - 1);

尽管您假设 long double 提供的尾数位数比 long long 的值位多,但是,您必须假设位移会溢出。

当然,您的 long double 可以表达更大的值,它们都是整数。但是它们没有单位精度,因此当 long double 的值较大时,您的 long double 的行为将与整数的预期行为不同。例如,如果 long double 变量 d 包含一个更大的值,那么 d + 1 == dd - 1 == d 中的至少一个可能计算为真。