为什么你可以在不进行类型转换的情况下将 long 存储到 float 中

Why can you store a long into a float without typecast

好的,所以我知道浮点数是 32 位十进制数。 Double 是 64 位十进制。 Long 是 64 位整数。那么为什么这个值是:Float(32 位) <- Long (64 位)。显然不是 java 代码,但我在 java 中引用了它。即使将其压缩为 32 位并失去精度,它也会自动进行转换。所以这意味着精度并不重要。但是 int <- double 不起作用,除非您明确地将 double 转换为 int。它的尺寸较小,它们都是数字,都是基元。这只是一般规则:十进制数 <- 整数,无论​​位大小如何。它只会循环回来。 java 中的 Numbers 中的规则和一切都有效吗?显示实际代码:

long L = 10_000L;
float f = L;

请注意,问题具体是关于 longfloat 没有显式转换,而不是 floatlong,而不是关于显式转换。

有隐式类型转换之类的东西。如果您不会丢失信息,Javajava 会自动转换它。从 float 到 long 你可能会丢失浮点数后面的所有内容,因此不会有隐式转换,因为通常你不想丢失此信息。

long 转换为 floatwidening primitive conversion。 Java 允许它没有错误,因为......它是这样定义的。来自 link:

19 specific conversions on primitive types are called the widening primitive conversions:

  • byte to short, int, long, float, or double

  • short to int, long, float, or double

  • char to int, long, float, or double

  • int to long, float, or double

  • long to float or double

...

A widening primitive conversion from int to float, or from long to float, or from long to double, may result in loss of precision - that is, the result may lose some of the least significant bits of the value. In this case, the resulting floating-point value will be a correctly rounded version of the integer value, using IEEE 754 round-to-nearest mode (§4.2.4).

(我的重点。)

为什么不需要显式转换就允许它?一般而言,只有当时在场的詹姆斯·高斯林 (James Gosling) 和其他人才能回答这类问题。对于我们其他人来说,答案是:因为规范就是这么说的。

但是,我会注意到,即使精度丢失,整体幅度也不会丢失,我敢打赌这就是它被允许的原因。 float 可以不精确地容纳 非常 大值。例如:

class Demo {
    public static void main(String[] args) {
        long l = Long.MAX_VALUE;
        float f = l;
        System.out.println(l);
        System.out.println(f);
    }
}

运行 然后你得到:

9223372036854775807
9.223372E18

9.223372e18 是 9223372000000000000。比较:

9223372036854775807 - the long value
9223372000000000000 - the float value

这是因为 float 可以牺牲值范围的精度,因为它存储一个基值,它会提高到一个指数。来自 Wikipedia's article on the IEEE-754 binary32 format(Java 的 float 是什么):

...an IEEE 754 32-bit base-2 floating-point variable has a maximum value of (2 − 2−23) × 2127 ≈ 3.402823 × 1038...

3.402823 × 1038 是:

340,282,300,000,000,000,000,000,000,000,000,000,000

...但是它可以存储的最高整数,这样你就可以加 1 而不会丢失精度只是 224- 1 (16,777,215)。它可以存储 16,777,216,但不能存储 16,777,217。所以 16,777,216 + 1 仍然是 16,777,216:

class Demo {
    public static void main(String[] args) {
        float f = 16_777_216f;
        System.out.println(String.format("%8.0f", f));     // 16777216
        System.out.println(String.format("%8.0f", f + 1)); // 16777216 (still)
    }
}

那是因为它现在存储的是基数除以 2,指数为 2,所以它不能再存储奇数了。越高越好,只能存储 4 的倍数,然后是 8 的倍数,然后是 16 的倍数,等等

对比一个long的maxiumum值,即263-1,也就是“只”:

9,223,372,036,854,775,807

但与float不同的是,它可以精确地表示每一个整数。