Java 如何处理多种类型的精度?
How does Java handle precision across multiple types?
在 Java 当我打印这样的东西时
System.out.println(1.0f*1l));
我得到了
的输出
1.0
或与
System.out.println(((byte)1)*'A');
我得到了
的输出
65
在这两种情况下,其中一种比另一种大。 Longs 是 64 位,而 float 是 32 位,bytes 是 8 位,而 chars 是 16 位。尽管如此,Java 还是以较小的类型输出结果。这不会被认为是精度损失吗?
Java 根据可能值的范围加宽类型。这意味着 float
被认为比 long
.
宽
非long
的整数运算也按int
执行。
byte * char
是 int
Java 语言规范提供了一个规则列表,用于管理基于操作数类型的结果类型。
特别是第 4.2.4 节说
If at least one of the operands to a binary operator is of floating-point type, then the operation is a floating-point operation, even if the other is integral.
这解释了为什么 float
"wins" 反对 long
.
整数运算在5.6.2节有解释。具体来说,它说
Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
• If either operand is of type double
, the other is converted to double
.
• Otherwise, if either operand is of type float
, the other is converted to float
.
• Otherwise, if either operand is of type long
, the other is converted to long
.
• Otherwise, both operands are converted to type int
.
这就是为什么在您的第二个示例中,结果 65 的类型为 int
。
你问的是 Binary Numeric Promotion (JLS 5.6.2)(强调我的):
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:
- If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).
- Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
- If either operand is of type
double
, the other is converted to double
.
- Otherwise, if either operand is of type
float
, the other is converted to float
.
- Otherwise, if either operand is of type
long
, the other is converted to long
.
- Otherwise, both operands are converted to type
int
.
表达式1.0f*1l
是float
和long
,所以long
转换为float
。
表达式((byte)1)*'A'
是一个byte
和一个char
,所以它们都被转换为int
。
除了其他详细说明规则的答案外,我认为也值得考虑为什么要这样。假设你这样做
2.7F * 2L
这个乘法的真正数学答案是 5.4。因此,如果答案是 long
,则它必须是 5L
(5 是最接近 5.4 的整数)。由于这种情况,将浮点值乘以整数的结果作为浮点值更有意义。如果打印以下代码行 5
.
,我认为在 Stack Overflow 上会有更多关于此的问题
System.out.println(2.7F * 2L);
实际上它打印 5.4
.
整数类型之间的所有操作(long
除外)都用int
完成也是有道理的。毕竟,byte
通常被认为是一个小数据包,而 char
通常被认为是一个字符。从这些角度来看,乘以 byte
或 char
值并不是真正有意义的。保持规则简单并仅使用 int
进行操作更有意义。
在 Java 当我打印这样的东西时
System.out.println(1.0f*1l));
我得到了
的输出1.0
或与
System.out.println(((byte)1)*'A');
我得到了
的输出65
在这两种情况下,其中一种比另一种大。 Longs 是 64 位,而 float 是 32 位,bytes 是 8 位,而 chars 是 16 位。尽管如此,Java 还是以较小的类型输出结果。这不会被认为是精度损失吗?
Java 根据可能值的范围加宽类型。这意味着 float
被认为比 long
.
非long
的整数运算也按int
执行。
byte * char
是 int
Java 语言规范提供了一个规则列表,用于管理基于操作数类型的结果类型。
特别是第 4.2.4 节说
If at least one of the operands to a binary operator is of floating-point type, then the operation is a floating-point operation, even if the other is integral.
这解释了为什么 float
"wins" 反对 long
.
整数运算在5.6.2节有解释。具体来说,它说
Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
• If either operand is of type
double
, the other is converted todouble
.• Otherwise, if either operand is of type
float
, the other is converted tofloat
.• Otherwise, if either operand is of type
long
, the other is converted tolong
.• Otherwise, both operands are converted to type
int
.
这就是为什么在您的第二个示例中,结果 65 的类型为 int
。
你问的是 Binary Numeric Promotion (JLS 5.6.2)(强调我的):
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:
- If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).
- Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
- If either operand is of type
double
, the other is converted todouble
.- Otherwise, if either operand is of type
float
, the other is converted tofloat
.- Otherwise, if either operand is of type
long
, the other is converted tolong
.- Otherwise, both operands are converted to type
int
.
表达式1.0f*1l
是float
和long
,所以long
转换为float
。
表达式((byte)1)*'A'
是一个byte
和一个char
,所以它们都被转换为int
。
除了其他详细说明规则的答案外,我认为也值得考虑为什么要这样。假设你这样做
2.7F * 2L
这个乘法的真正数学答案是 5.4。因此,如果答案是 long
,则它必须是 5L
(5 是最接近 5.4 的整数)。由于这种情况,将浮点值乘以整数的结果作为浮点值更有意义。如果打印以下代码行 5
.
System.out.println(2.7F * 2L);
实际上它打印 5.4
.
整数类型之间的所有操作(long
除外)都用int
完成也是有道理的。毕竟,byte
通常被认为是一个小数据包,而 char
通常被认为是一个字符。从这些角度来看,乘以 byte
或 char
值并不是真正有意义的。保持规则简单并仅使用 int
进行操作更有意义。