为什么你可以在不进行类型转换的情况下将 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;
请注意,问题具体是关于 long
到 float
没有显式转换,而不是 float
到 long
,而不是关于显式转换。
有隐式类型转换之类的东西。如果您不会丢失信息,Javajava 会自动转换它。从 float 到 long 你可能会丢失浮点数后面的所有内容,因此不会有隐式转换,因为通常你不想丢失此信息。
将 long
转换为 float
是 widening 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
不同的是,它可以精确地表示每一个整数。
好的,所以我知道浮点数是 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;
请注意,问题具体是关于 long
到 float
没有显式转换,而不是 float
到 long
,而不是关于显式转换。
有隐式类型转换之类的东西。如果您不会丢失信息,Javajava 会自动转换它。从 float 到 long 你可能会丢失浮点数后面的所有内容,因此不会有隐式转换,因为通常你不想丢失此信息。
将 long
转换为 float
是 widening primitive conversion。 Java 允许它没有错误,因为......它是这样定义的。来自 link:
19 specific conversions on primitive types are called the widening primitive conversions:
byte
toshort
,int
,long
,float
, ordouble
short
toint
,long
,float
, ordouble
char
toint
,long
,float
, ordouble
int
tolong
,float
, ordouble
long
tofloat
ordouble
...
A widening primitive conversion from
int
tofloat
, or fromlong
tofloat
, 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
不同的是,它可以精确地表示每一个整数。