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

时间:2009-12-04 18:12:07

标签: types floating-point double ieee-754

什么是最大的“非浮动”整数,可以存储在IEEE 754双精度型中而不会丢失精度?

9 个答案:

答案 0 :(得分:458)

可以存储在double中而不会丢失精度的最大/最大整数与double的最大可能值相同。也就是说,DBL_MAX或大约1.8×10 308 (如果你的双倍是IEEE 754 64位双倍)。这是一个整数。它完全代表了。你还想要什么?

继续,问我最大的整数是什么,这样它和所有较小的整数可以存储在IEEE 64位双精度而不会丢失精度。一个IEEE 64位双尾有52位尾数,所以我认为它是2 53

  • 2 53 + 1无法存储,因为开头的1和末尾的1之间有太多的零。
  • 可以存储少于2 53 的任何内容,其中52位明确存储在尾数中,然后指数实际上为您提供另一个。
  • 显然可以存储
  • 2 53 ,因为它的功率很小。

或另一种看待它的方式:一旦偏离指数被取消,并忽略符号位与问题无关,则double存储的值是2的幂,再加上52位整数乘以2 指数 - 52 。因此,使用指数52,您可以存储从2 52 到2 53 的所有值 - 1.然后使用指数53,您可以在2 之后存储下一个数字53 是2 53 + 1×2 53 - 52 。因此,首先发生2 53 + 1的精度损失。

答案 1 :(得分:68)

9007199254740992 (即9,007,199,254,740,992)无保证:)

程序

#include <math.h>
#include <stdio.h>

int main(void) {
  double dbl = 0; /* I started with 9007199254000000, a little less than 2^53 */
  while (dbl + 1 != dbl) dbl++;
  printf("%.0f\n", dbl - 1);
  printf("%.0f\n", dbl);
  printf("%.0f\n", dbl + 1);
  return 0;
}

结果

9007199254740991
9007199254740992
9007199254740992

答案 2 :(得分:25)

维基百科在相同的上下文中提到了IEEE 754的链接:

  

在典型的计算机系统中,“双精度”(64位)二进制浮点数的系数为53位(其中一个是隐含的),指数为11位,一个符号位。 / p>

2 ^ 53刚刚超过9 * 10 ^ 15.

答案 3 :(得分:13)

可以用IEEE 754 double(64位)表示的最大整数与该类型可以表示的最大值相同,因为该值本身就是一个整数。

这表示为0x7FEFFFFFFFFFFFFF,由以下内容组成:

  • 符号位0(正)而不是1(负)
  • 最大指数0x7FE(2046表示减去偏差后的1023)而非0x7FF(2047表示NaN或无穷大)。
  • 最大尾数0xFFFFFFFFFFFFF,即52位全部为1。

在二进制中,值是隐式1,后跟尾数中的另外52个,然后是指数的971个零(1023 - 52 = 971)。

确切的十进制值是:

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368

这大约是1.8 x 10 308

答案 4 :(得分:8)

您需要查看尾数的大小。 IEEE 754 64位浮点数(具有52位,加上1隐含)可以精确地表示绝对值小于或等于2 ^ 53的整数。

答案 5 :(得分:6)

答案 6 :(得分:2)

确实,对于 64 位 IEEE754 double,可以精确表示 9007199254740992 == 2^53 以内的所有整数。

然而,还值得一提的是,所有超过 4503599627370496 == 2^52 的可表示数都是整数。 超过 2^52 测试它们是否是整数变得毫无意义,因为它们都隐式地四舍五入到附近的可表示值。

在 2^51 到 2^52 的范围内,唯一的非整数值是以“.5”结尾的中点,这意味着计算后的任何整数测试都必须预期产生至少 50% 的错误答案。< /p>

在 2^51 以下我们还有“.25”和“.75”,因此将一个数字与其四舍五入的对应物进行比较以确定它是否可能是整数开始有意义。

TLDR:如果要测试计算结果是否可能是整数,请避免大于 2251799813685248 == 2^51 的数字

答案 7 :(得分:1)

来自DECIMAL_DIG

<float.h>应该至少给出一个合理的近似值。因为它处理十进制数字,并且它实际上存储在二进制中,所以你可以存储一些 little 更大而不会丢失精度的东西,但确切地说有多少。我想你应该能够从FLT_RADIXDBL_MANT_DIG弄明白,但我不确定我是否完全相信结果。

答案 8 :(得分:0)

正如其他人所指出的,我将假设 OP 要求最大的浮点值,以便所有小于自身的整数都可以精确表示。

您可以使用 pos, neg := adder, adder 中定义的 FLT_MANT_DIGDBL_MANT_DIG 来不依赖显式值(例如,53):

float.h

输出:

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

int main(void)
{
    printf("%d, %.1f\n", FLT_MANT_DIG, (float)(1L << FLT_MANT_DIG));
    printf("%d, %.1lf\n", DBL_MANT_DIG, (double)(1L << DBL_MANT_DIG));
}