7

查看 Java(但在其他语言中可能相似或相同),long 和 double 都使用 8 个字节来存储一个值。

long 使用 8 个字节存储从 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 的长整数

double 使用 8 个字节来存储从 -1.7E308 到 1.7E308 的双精度浮点数,最多 16 个有效数字。

我的问题是,如果两者都使用相同的字节数(8 字节或 2^64),如何双倍存储更长的数字?1.7E308 比 9,223,372,036,854,775,807 大得多。

4

4 回答 4

7

您可以在 64 位中存储的绝对信息量当然是相同的。

改变的是您分配给这些位的含义。

integerorlong变量中,使用的编码与您在日常生活中使用的十进制数字相同,除了使用了第二个补码这一事实,但这并没有太大变化,因为它只是获得的一个技巧一个额外的数字(同时只存储一个零而不是一个正数和一个负数)。

在 float 或 double 变量中,位分为两种:尾数和指数。这意味着每个双精度数的形状都像XXXXYYYYY它的数值一样XXXX*2^YYYY。基本上你决定以不同的方式对它们进行编码,你得到的是你有相同数量的值,但它们以不同的方式分布在整个实数集上。

浮点数的最大/最小值大于/小于整数的最大/最小值这一事实并不意味着有效存储的数据量有任何影响。

于 2013-09-08T17:51:00.197 回答
2

本质上,双精度数可以通过在它可以存储的数字之间具有更大的间隔来存储更大的数字。并非双精度范围内的每个整数都可以由该双精度表示。

更具体地说,双精度位 (S) 用于存储符号,11 位用于存储指数 E,以及 52 位精度,即所谓的尾数 (M)。

对于大多数数字(有一些特殊情况),双精度数存储数字 (-1)^S * (1 + (M * 2^{-52})) * 2^{E - 1023},因此,当 E 很大时,将 M 更改 1 会使结果数的大小变化比 1 大得多。这些巨大的差距使双倍的范围比多头更大。

于 2013-09-08T17:43:07.780 回答
0

Long 或 int 是有符号的实体,可以是正数或负数,但不能有任何小数部分。

浮点型或双精度型在计算机中用于表示具有小数部分的数字。

long 和 double 都是 64 位。Long 有 1 位用于有符号(确定正数或负数),其余 63 位组成数字。所以范围可以是 -2^63 到 2^63-1

双精度数以 IEEE 二进制浮点算术标准指定的不同方式表示,旨在在计算机中存储非常大的数字。64 位双精度表示为 - [1 位][11 位指数][52 位尾数]

让我们看一个例子,将 100.25 转换为存储为双精度的二进制形式

  1. 十进制 100.25 转换成二进制是 1100100.01
  2. 然后将二进制 1100100.01 归一化为 1.10010001 * 2^6
  3. 6 是指数成分。我们选择 base 或 offset 为 1023,以便可以正确表示负数和正数。所以 6+1023=1029 是添加偏置后的偏移指数分量。100000011 是指数的二进制表示。

  4. 为了从 1.10010001 计算尾数,我们忽略小数点右边的 1,只使用小数点右边的所有数字(即 10010001),并用零填充任何剩余的 52 位。所以,现在尾数将是 1001 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

  5. 因此,最后 64 位表示为有符号位指数尾数 0 100000011 1001 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

于 2013-09-08T21:52:19.903 回答
0

阅读上面的Delimanolis语句,我测试了 long-to-double 转换中的精度损失 - 忽略了 500 大的整数值(见下文)。

long L;
double D;

L = 922_3372_0368_5477_5807L;
L -= 500;
D = L;
L = (long)D;

System.out.println("D and L: " + D + " " + L);

输出

D and L: 9.223372036854776E18 9223372036854775807
于 2019-08-16T05:45:35.127 回答