长整型和双精度浮点型的大小让我困惑了

8

观察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),double如何存储更长的数字?1.7E308比9,223,372,036,854,775,807大得多。


3
它有可能会失去一些精度。请阅读http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html。 - Sotirios Delimanolis
http://en.wikipedia.org/wiki/Floating_point - SLaks
因为您可以将1添加到任何长整数,但是您无法将1.0添加到某些double中,例如1.6E308。或者,如果您想要能够添加0.00000000001,则您的双精度数不能超过1.0,这比长整数小得多。 - huseyin tugrul buyukisik
计算机中存储浮点数的方式相当于指数表示法(类似于“1.234E56”,只不过是二进制)。另一方面,intlong值则以普通数字的计算机等效形式存储(例如12345678,没有小数点和指数)。浮点/双精度数的范围更大,但精度较低。 - Hot Licks
据我研究,Java的double类型可以存储15位有效十进制数字。然而,一个长数字可以达到19位(922...)。因此,问题应该是“15位容量如何包含19位数字”。因此,https://stackoverflow.com/users/2662723/user2662723 的最后一句话令人困惑。 - Park JongBum
4个回答

7

在64位中,你可以存储的信息绝对数量是相同的。

改变的是你对比特位赋予的意义。

在整数或长整数变量中,使用的编码方式与你在日常生活中使用的十进制数字相同,除了使用了二进制补码。但这并没有改变太多,因为这只是一种技巧,在存储一个零而不是正数和负数时获得一个额外的数字。

在浮点数或双精度变量中,比特位分为两种:尾数和指数。这意味着每个双精度数字的形式为XXXXYYYYY,其中它的数值是类似于XXXX*2^YYYY的东西。基本上,你决定以不同的方式编码它们,你获得的是相同数量的值,但它们在整个实数集中分布的方式不同。

浮点数的最大/最小值比整数的最大/最小值大/小,并不意味着有效存储的数据量有所改变。


2

双精度浮点数通过其可以储存的数字间隔更大,从而能够存储更大的数字。但并不是每个整数都能被双精度浮点数表示。

更具体地说,双精度浮点数有一个比特位(S)来存储符号,11个比特位来存储指数E,以及52个比特位的精度,在所谓的尾数(M)中。

对于大多数数字(有一些特殊情况除外),双精度浮点数存储的数字为(-1)^S * (1 + (M * 2^{-52})) * 2^{E - 1023}。因此,当E很大时,将M改变1将比1产生更大的结果数值变化。这些大间隔给了双精度浮点数比长整型更大的范围。


0

长整型或整型是有符号实体,可以是正数或负数,但从不具有任何小数部分。

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

长整型和双精度类型都是64位。 长整型有1位用于符号(确定正数或负数),其余63位组成数字。因此,它们的范围可以是-2^63到2^63-1

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

让我们通过一个例子来看看如何将100.25转换为存储为双精度类型的二进制形式

十进制数100.25转换为二进制为1100100.01 二进制数1100100.01进行规格化后为1.10010001 * 2^6 其中6为指数部分,我们选择将基数或偏移量设为1023,以便可以正确表示正负两种情况。因此,偏移后的指数部分为6+1023=1029,加上偏置。100000011是指数的二进制表示。 要从1.10010001计算尾数,我们忽略小数点右侧存在的1,并只使用小数点右侧的所有数字(即10010001),并使用零填充任何剩余的52位。因此,现在尾数将为1001 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000。 因此,最终64位将表示为 带符号位 指数 尾数 0 100000011 1001 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

0

阅读Delimanolis上面的声明后,我测试了长整型转双精度浮点型时的精度损失 - 一个像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

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