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


Answers:


506

可以存储在double中而不丢失精度的最大/最大整数与double的最大可能值相同。即DBL_MAX约1.8× 10308(如果您的double是IEEE 754 64位double)。这是一个整数。准确地表示出来。您还想要什么?

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

  • 无法存储2 53 + 1,因为开始处的1和结束处的1之间有太多零。
  • 可以存储少于2 53的任何内容,其中52位明确存储在尾数中,然后有效的指数又为您提供了一位。
  • 显然可以存储2 53,因为它是2的小幂。

或以另一种方式看待它:一旦去除了指数的偏差,并且忽略了与问题无关的符号位,则双精度值存储的值为2的幂,再加上一个52位整数乘以2 指数-52。因此,对于指数52,您可以存储从2 52到2 53  − 1的所有值。然后对于指数53,在2 53之后可以存储的下一个数字是2 53 +1×2 53-52。因此精度损失首先出现在2 53 + 1处。


126
+1很好,注意到该问题并不真正意味着询问者可能打算做什么,并提供了两个答案(“技术上正确”和“可能预期”)。
Pascal Cuoq,

62
还是“打扰”和“试图帮助”,我倾向于称呼它们为:-)
史蒂夫·杰索普

8
我向小马托尼鞠躬,别无其他。
Steve Jessop

11
您并不是指“所有较小的整数”,而是指所有大小相等或更小的整数。因为在2 ^ 53以下有很多负整数,不能精确地用双精度表示。
南部款待

13
我的意思是说更小,这就是我说的更小的意思:-) -1,000,000小于1,但不小于1。
史蒂夫·杰索普

77

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

7
假设它将“接近”但小于2 ^ N,则将进行更快的测试double dbl = 1; while (dbl + 1 != dbl) dbl *= 2; while (dbl == --dbl);,得出相同的结果
Seph

4
@Seph什么...?没有?while (dbl == --dbl)将永远循环或根本不循环。:)(在这种情况下,根本没有,因为它是2 ^ N)。您必须从下面接近它。实际上,它也会导致比预期结果少一(因为while循环中的一检查减少了dbl)。而且,递减是在评估左侧之前还是之后进行的,这取决于执行顺序(据我所知这是未定义的)。如果是前者,它将始终为真并永远循环。
falstro

10
也许表明2 ^ 53 = 9,007,199,254,740,992在某处。
Xonatron

1
这很难争论!不错的实验
MattM

一个弱点使用while (dbl + 1 != dbl) dbl++;dbl + 1 != dbl使用可评估long double的数学-考虑FLT_EVAL_METHOD == 2。这可能会陷入无限循环。
chux-恢复莫妮卡

25

Wikipedia在同一上下文中也提到了指向IEEE 754的链接:

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

2 ^ 53刚好超过9 * 10 ^ 15。


@Steve Jessop或多或少,这的确是我的意思。我还遇到了没有FPU且仍需要符合IEEE要求的硬件系统,因此,如果我在8个月后回到这里并需要相同的信息,“典型系统”的内容并不能真正为我提供帮助我的基于68K的微控制器(假设它没有FPU ...我不记得了)。
圣哈辛托2009年

14
@San Jacinto-“这没用”太苛刻了。答案是非常有用的,只是没有包含典型计算机系统确实使用IEEE 754代表的注释。
Stephen C. Steel

@Stephen C. Steel,实际上你是对的。在我的情况下,稍后再回过头来寻找IEEE max,关于“典型系统”是什么模棱两可是不可能的,但是除了这种抱怨之外,答案还值得一提。
圣哈辛托2009年

20

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

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

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

用二进制表示,值是隐式1,尾数是52,然后是指数的971个零(1023-52 = 971)。

确切的十进制值为:

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766871171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274834826360284

这大约是1.8 x 10 308


它所能代表的最大值与介于0和0之间的所有值可以连续表示吗?
亚伦弗兰克

@AaronFranke该问题并未询问连续表示,但此处其他大多数答案中都包含了对该问题的答案,甚至错误地给出了实际答案。它是2×3(2等于53的幂)。
西蒙·比伯

8

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


8
它也可以精确表示2 ^ 53 :-)
史蒂夫·杰索普

6

2
引用此答案会更好。
圣哈辛托

2
@Carl,如果整数在左边超出零,则将其精确存储。
威廉

4
@all downvoters:1.7976931348623157×10 ^ 308 一个精确的整数。你们都需要参加数学补习班吗?
Dan Moulding)2009年

6
在讨论这个毫无希望的沉没答案时,我们只涉及语义。的确,该数字可以准确表示,从而满足问题的要求。但是我们都知道,这是在一个未命中的海洋中的一个小小的精确岛,我们大多数人正确地将这个问题插值为“最大的数字,超出这个数字就会使效率下降”。啊,CompSci是一门精确的科学难道不是很好吗?:)
Carl Smotricz 09年

2
@DanMoulding 1.7976931348623157×10 ^ 308是一个精确的整数,但是我敢肯定这个特定的整数不能精确地存储为双精度。
Pascal Cuoq 2014年

2

DECIMAL_DIGfrom <float.h>应该至少给出一个合理的近似值。因为带小数点的数字是交易,它的真正存储在二进制,你大概可以存储的东西有点不失精度较大,但到底有多少还很难说。我想您应该能够从FLT_RADIX和中找出答案DBL_MANT_DIG,但是我不确定我是否完全相信结果。


这不能为问题提供答案。要批评或要求作者澄清,请在其帖子下方发表评论。
MichaelChirico 2015年

@MichaelChirico:这回答了他打算问的问题,就像写答案时一样。要查看问题的编辑历史记录,请单击问题底部的“ 14年19月19日编辑于11:40”链接。
杰里·科芬

您的答案读起来像是一条评论,因为它似乎缺乏答案应具有的信心/权威性(“应该至少给出一个合理的价格……”“确切地说……多少很难说”“我想... ”)。我对所问的问题或答案没有专业知识,所以我可能是错的。只需输入我的2分钱(我是从审核队列中发送给我的)(我想这意味着其他用户已标记了您的答案)。
MichaelChirico 2015年

1
@MichaelChirico:他们很可能拥有-您与唯一一个对主题一无所知的人相去甚远;让您与众不同的是您意识到自己对此一无所知。对于C语言中的浮点数的精度来说,大多数听起来权威的答案都是错误的。例如,上面的许多(大多数)错误假设都是基于a double直接对应于特定IEEE类型的,但这不是必需的,并且在撰写此答案时,问题也没有提到特定的IEEE类型。
杰里·科芬

得到它了。我也许建议将这些信息添加到答案中。
MichaelChirico
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.