问题描述
编辑:在评论中进行了一些讨论后发现,由于在 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 == d
和 d - 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_BIT
和 sizeof( 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。