Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 计算长双倍于叮当声–;编译器错误?_C_Clang - Fatal编程技术网

C 计算长双倍于叮当声–;编译器错误?

C 计算长双倍于叮当声–;编译器错误?,c,clang,C,Clang,这是叮当作响的虫子吗 这将打印出最大双倍值: long double a = DBL_MAX; printf("%Lf\n", a); long double a = LDBL_MAX; printf("%Lf\n", a); 它是: /* … bigger, but not displayed here. For a good reason. ;-) */ 179769313486231570814527423717043567908070705655675258444996598917

这是叮当作响的虫子吗

这将打印出最大双倍值:

long double a = DBL_MAX;
printf("%Lf\n", a);
long double a = LDBL_MAX;
printf("%Lf\n", a);
它是:

/* … bigger, but not displayed here. For a good reason. ;-) */
17976931348623157081452742371704356790807070565567525844499659891747680315726078089563276687817154045895351438246423432132688946418227684675467035516986049910576551282076245490038932894407585845513394583236903222981658085332334827479262626244723168738177180919299888840402848368.000000

这将打印出最大长双精度值:

long double a = DBL_MAX;
printf("%Lf\n", a);
long double a = LDBL_MAX;
printf("%Lf\n", a);
它是:

/* … bigger, but not displayed here. For a good reason. ;-) */
这是很清楚的

但当我使用一个算术表达式,即编译时可计算的初始值设定项时,我得到了一个令人惊讶的结果:

long double a = 1.L + DBL_MAX + 1.L;
printf("%Lf\n", a); 
这仍然打印出DBL_MAX,而不是DBL_MAX+2

如果在运行时完成计算,则情况相同:

long double b = 2.L;
long double a = DBL_MAX;
printf("%Lf\n", a+b);
仍然是DBL_MAX

$ clang --version
Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin12.4.0
Thread model: posix

这是预期的行为

long double a = 1.L + DBL_MAX + 1.L;
long double
类型是浮点型:它具有有限的精度。大多数运算的结果四舍五入到最接近的可表示值


请参阅。

不是一个buglong double具有64位精度,结果将四舍五入以适合该格式

如果我们使用十六进制而不是二进制,这将更加清晰<代码>DBL_MAX是:

0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
因此,
1.L+DBL_MAX
的精确数学结果为:

0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
。。。但这不能表示为
长双精度
,因此计算结果被四舍五入到最接近的可表示的
长双精度
,即
DBL_MAX
;添加
1
不会(也不应该)更改该值

(它向下舍入而不是向上舍入,因为下一个较大的可表示数字是

0xfffffffffffff801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

这比DBL_MAX更远离数学上精确的结果。

IEE754浮点
double
的尾数为53位宽(52个物理+1个隐式位)。这意味着
double
可以准确地表示
-2^53…+2^53
范围内的连续整数(即从
-9007199254740992
+9007199254740992
)。之后,该类型就不能再精确地表示连续整数了。相反,该类型只能表示偶数整数值。根据一些特定于实现的规则,任何奇数值都将四舍五入到相邻的偶数值。因此,在
double
中向
9007199254740992
添加
1
可能会由于舍入而导致结果为零。从该限制开始,您必须添加至少
2
,以查看值的变化(直到您达到添加
2
将停止任何效果的点,并且您必须添加至少
4
,依此类推)

如果平台上的长双精度大于双精度,则相同的逻辑适用于长双精度。在x86上,long double可能指的是硬件80位浮点类型和64位尾数。这意味着即使使用这种类型,连续整数的精确表示范围也仅限于
-2^64…+2^64


DBL_MAX
的值是far,far,FAAAAR超出该范围。这意味着尝试将
1
添加到
DBL_MAX
不会对该值产生任何影响。添加
2
也不会有任何效果。既不会
4
,也不会
1024
,甚至也不会
4294967296
。您必须在
2^960
区域(实际上是
nextafter(2^959)
)中添加一些内容,以便对以80位
长双精度格式存储的
DBL\u MAX
值产生影响。

这是一个技术上不太正确的答案,希望能帮助:

数字由符号、指数和分数表示

在本页中,提供了有关C数据类型的信息()。图表声称长双精度数据不能保证是比双精度数据“更大”的数据类型;但是,由于C99,如果目标体系结构上存在,则可以保证这一点(附录F IEC 60559浮点算法)。来自
DBL_MAX
LDBL_MAX
的结果表明,在您的实现中,它实际上使用了更多的位

下面是正在发生的事情:

您有以下格式的数字:

如果是双倍的话

在long中,有一个80位表示()

您可以将double类型放入长double类型中,这样就不会产生任何问题。但是,请注意,小数点是“浮动的”(因此得名),并不是数字中的所有数字都表示出来。计算机表示最重要的数字,然后是和指数(因此这就像我写1234567 E 234,例如,请注意,我没有写该数字的所有234位)。当您尝试向其中添加1时,将不表示1所在位置的数字(由于指数的大小),因此四舍五入后将忽略该数字


有关更多详细信息,请在此处阅读浮点()

如果long double in clang只有64位,为什么LDBL_MAX大于DBL_MAX?@AndrewW:64位精度;它是80位类型。(而double是一种64位类型,精度为53位)。在前16位左右之后,其余数字没有意义;
double
类型根本不存储任何数字。是的,是的,是的,我很笨。当然,我知道,但我不记得了+非常感谢。我只是忘了+1.