Java 中float(浮点类型)为什么能直接接收long(整数类型)

最为一个常识,我们都知道浮点型在内存中占用的是 4 个字节的空间,而 long 型占用的是 8 个字节的空间。可是为什么 4 个字节的 float 型的最大值会大于 long 型的最大值呢?
  我们都知道,float 类型的范围是:一 3.403E38~3.403E38。而 long 类型的范围是:-2^63~2^63-1(大概是 9*10^18)。
  我以前也是简单的记住就算完事了,对于它为什么会这样却没有考虑过。
  下面给大家分享一下我现在的理解:
  long 整型数,在内存中占用 8 个字节共 64 位,它表示的数值有 2 的 64 次方,平分正负,数值范围是负 2 的 63 次方到正 2 的 63 次方 - 1。
  而 float 在内存中占 4 个字节,共 32 位,但是浮点数在内存中是这样的:
  V=(-1)^s * M * 2^E
   667x190
  浮点数的 32 位不是简单的直接表示大小,而是按照一定的标准分配的。
  其中第 1 位,符号位,即 S。
  接下来的 8 位,指数域,即 E。
  剩下的 23 位,小数域,即 M,M 的取值范围为 [1,2)或 [0,1)。
  也就是说,浮点数在内存中的二进制值不是直接转换为十进制数值的,而是按照上述公式计算而来,通过这个公式,虽然只用到了 4 个字节,但是浮点数却比长整型的最大值要大。

  这也就是为什么在数据转换的时候,long 类型转换为 float 类型的根本原因所在!

 

一个数据在计算机的内存中保存时,需要一定的空间,这种 “空间” 由程序中的“数据类型”(比如 int/long/float)来告诉编译器。
在数据类型所占用的空间范围内的数据,可以进行类型转换或者强制类型转换,也许会有一些误差,但一般不会出现离奇的 “错误的结果”
另外,占用空间小的数据类型(比如 int)向占用空间大的数据类型(比如 long)转换,一般也不会出现 “错误的结果”
但是反过来,占用空间大的数据类型向小的数据类型转换时,由于有可能会丢失数据的精度,所以编译器会提示错误;这个时候可以选择强制类型转换,但有时会得到 “意想外的结果”

Java 中规定:
int 占用 4 个字节
long 占用 8 个字节
float 占用 4 个字节

int 和 long 的转换很容易理解,
4 个同学去有 4 张床位的寝室和去有 8 张床位的寝室,都能很好的容纳;
8 个同学去有 8 张床位的寝室,没有问题;去仅有 4 张床位的寝室就容纳不下了。

楼主问的问题可以转化为:为什么 long 型占用 8 个字节,但相对于仅占用 4 个字节的 float 时的行为却很像 “小数据类型”
(为什么 long 可以转换为 float,而反过来 float 转换为 long 时,有时会出问题)

Java 语言数据类型之间的合法转换

6 个实心箭头代表无数据丢失的转换
3 个虚心箭头代表可能有精度损失的转换
没有箭头的代表通常不能进行转换
(参考:JAVA 核心技术 卷 I:基础知识 图 3-1)

核心技术的作者给出的例子如下:
int n = 123456789;
float f = n; // f is 1.23456792E8
从 n 到 f 转换时,虽然得到了同样大小的结果,但却失去了一定的精度。

说白了就是 long 型虽然占用 8 个字节,但是由于要非常严密精确的表达每一位数,
能够表达的数的范围,反倒没有占用 4 个字节的 float 型能够表达的数据范围大

posted @ 2018-05-03 17:47  木头的心  阅读(3526)  评论(0编辑  收藏  举报