Double.toString(d)的最大长度是多少?

9

我的实验表明,边界为24,该边界由-Double.MIN_NORMAL达到,其结果为

-2.2250738585072014E-308

......但我无法证明它,也不能得出任何结论,说明为什么没有其他值能够超过-MIN_NORMAL


长度是指字符数吗?是什么引起了你对此的好奇心? - Sotirios Delimanolis
4
看着我手头有的(有点老旧的)Java源代码,分配的缓冲区(在sun.misc.FloatingDecimal内部)大小为26个字符。因此,那可能是一个上限。 - Hot Licks
@HotLicks:你知道那是哪个版本,这个绑定在源代码的哪里找到吗? - Louis Wasserman
(请注意,FloatingDecimal 很可能可以表示比 double 更大的数字,因此很容易相信 26 大于 double 所需的大小。但是,正如我所说,这是一个上限。) - Hot Licks
1
在配置了西班牙语环境的JVM中,要小心负无穷大,它是-Extremadamentemierdaenorme,共27个字符。 - Glenn Lane
显示剩余5条评论
3个回答

5

这是一个64位的IEEE-754浮点数。

52位尾数可以存储的最大十进制数是17(参见第4页ceil( 1 + N Log10(2) )),所以带有小数点和负号的数值最长为19个字符。

偏移量为1023,因此最小的基数指数是2^-1022,约为10^-308,所以最长的指数为5个字符,并带有'E'和负号。

19 + 5 == 24


你有“52位尾数中可存储的最多十进制数字为17”的引用吗? - Louis Wasserman
@LouisWasserman - 通过将一个52位的全1二进制数转换为十进制来确认这将很容易。 - Hot Licks
你可以使用例如Windows计算器的工具,从十六进制开始以13个"F"数字开头,然后转换为十进制。 - Hot Licks
System.out.println(Long.toString((1L << 52) - 1).length()); 返回的是16,或者我翻译错了吗? - Louis Wasserman
尾数是小数点右边的基数2。最重要的位是1/2,接着是1/4,然后是1/8,以此类推。我已经更新了我的答案,并附上了一个解释链接。 - Glenn Lane

1

26似乎是一个上限,具体如下。

根据GrepCode的FloatingDecimal.getChars版本,OpenJDK7 断言nDigits最多为19。从代码来看,nDigits似乎是指尾数(而非小数点)的数字,在上面的示例中,是22250738585072014。然后,其他字符包括:

  • 值整体上的-符号
  • .小数点
  • 指数用的E
  • 指数上的-符号
  • 最多三位小数的指数

这样就有19 + 7 = 26个字符。

(对于更严格的界限的论证仍然受欢迎。)


0

我认为这个界限是正确的。javadoc说:

必须打印多少位小数部分的 ma? 必须至少有一位数字来表示小数部分,除此之外还需要尽可能多的数字,但只需要足以唯一地区分类型 double 的相邻值。

一个 double 有一个隐含的整数部分 (1) 和 52 个尾数位。因此,如果由 double 表示的基数2指数为0,使得 x 是范围在 [1,2) 的 double,那么下一个更高的相邻 doublex + 2-52。2-52 大约是 2.2204 * 10-16。这表明区分一个值与下一个相邻值所需的小数位数为16,即1旁边的双倍数将表示为 1.0000000000000002(15个零)。由于这与您的实验中的小数位数匹配,因此很可能确实是永远需要的最大数量。当然,这不是严格的证明;这需要更多的工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接