可以存储在 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 中的条件 DBL_MAX

总是在同一个答案中,他们说 double 的最大可能值是 printf("%e\n",LDBL_MAX); 或大约 1.8 x 10^308。
我不知道这是什么意思,但如果我运行

%Le

我每次都会得到一个不同的值,它总是在 6.9 x 10^(-310) 左右。
编辑:我应该使用 LDBL_MAX,获得大约 1.19 x 10^4932 的值作为输出)
我从 here 拿走了 printf("%d\n",LDBL_MAX_10_EXP);

我也试过这个

4932

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

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

有人能告诉我如何找出可以存储为 {{1}} 的最大整数是多少吗?

解决方法

鉴于您在评论中表示要使用 long double 代替 long long 来获得更大的范围,因此我假设您还需要单位精度。因此,您要求浮点表示 (LDBL_MANT_DIG) 的基数中可用尾数位数 (FLT_RADIX) 表示的最大数。在很可能出现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 变量 d 包含更大的值,那么 d + 1 == dd - 1 == d 中的至少一个可能会评估为真。

,

您可以使用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。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...