无法理解长双精度数如何大于 2^80

Can't understand how a long double number can be greater than 2^80

所以我正在求解泰勒级数,它在这里:

这是代码:

#define _CRT_SECURE_NO_WARNINGS 
#include<conio.h>  
#include<stdio.h>  
#include<math.h>  
long double Fact(long double h) { 
if (h <= 0) return 1; 
else return h*Fact(h - 1); 
 } 

void main(void) { 
int p = 0; 
long double s = 0, k = 0, c = 0, l = 0,d=0; 
int n = 0, x = 0; 
printf(" n "); 
scanf("%d", &n);  
printf(" x "); 
scanf("%d", &x); 
d = x; 
while (n>=0) { 
  k = pow(-1, n); 
  c = (2 * n + 1); 
  l = Fact(c); 
  d = pow(x, 2 * n + 1);  
  s = s+ ((k / l)*d); 
  n = n - 1; 
   } 
printf("Result : %.16LG\n", s); 
_getch(); 
 }

问题是:如果我输入 n = 16x = 2,147,483,646 但它仍然写出正确的结果(我将程序的结果与沃尔夫拉姆阿尔法)

假设你说的是 2^80,因为你假设大小为 80 位的浮点数最多只能存储 280。您对浮点数的理解是错误的。与将数字编码为二进制数的无符号整数不同,浮点数的编码不同。

您可以在 wikipedia 上了解更多,但基本思想是浮点数编码为

sign * something * 2^something_else

这里的重要部分是 2^something_else。对于 32 FP 数字 something_else(指数)是 8 位长,因为一些特殊情况意味着对于普通数字它可以从 −126+127,对于 long double 假设它是 80 位x86 FP 它可以转到 16383:

让我们假设我决定发明我自己的数据类型,我称之为 bloat(比如 float,geddit?)。这种类型只有一个字节宽(8 位)并使用以下表示:位 #0(最低有效位)的权重为 40 = 1,位 #1 的权重41 = 4,位 #2 的权重为 42 = 16,位 #3 的权重为 43 = 64 依此类推。

bloat 中的位 00010001 的组合将代表 1 + 256 = 257bloat 中可表示的最大值为 11111111,即 21845。所以,你是这样的:使用我新发明的 bloat 类型,我设法在仅 8 位内存中表示值 2184521845 大于 214,但我设法将它压缩成 8 位!我是怎么做到的?

简单:为了 "stretch" 我的类型的明显范围,我牺牲了一些中间值。例如,我的 bloat 类型不能表示数字 2。它不能表示数字 66。等等。 21845下有很多我的bloat无法表示的值。如果你计算我的 bloat can 代表的所有可能的不同值,你会发现正好有 256 个,即恰好 28 可以表示不同的值。

浮点类型,例如您的 long double 对 "stretch" 它们的范围采用几乎相同的原理。它们的内部格式和属性比我的bloat更复杂,但基本思想是一样的:80位浮点类型的绝对范围比280大得多 因为它 "skips"(无法表示)该范围内的很多值。

它们内部表示的确切细节是 widely available on the Net

x86 扩展精度格式(如果这是导致您引用 80 位的原因)有 63 个尾数位和 15 个指数位(偏差为 16383,保留值 32767)。

因此它可以表示的最大值非常接近 2 x 2^(32766-16383) ~ 1.189731 x 10^4932,比 2^80 大很多很多。

普通 IEEE 双精度的最大可表示数约为 1.79769 x 10^308。