最大Java空头(32767)加1不转负?
Largest Java Short (32767) plus 1 not turning negative?
最近学习了二元制中表示正整数和负整数的补码法。然后,我尝试使用 java 和以下短代码来查看实际效果:
int a=2147483647;
System.out.println("a: "+a);
System.out.println("a+1: "+(a+1));
short b=32767;
System.out.println("b: "+b);
System.out.println("b+1: "+(b+1));
输出:
a: 2147483647
a+1: -2147483648
b: 32767
b+1: 32768
这让我很困惑,因为我认为 b+1,用二进制表示为 011111111111111,会变成 1000000000000000,或者用十进制表示 -32768。怎么回事?
虽然 b
是一个短整型,但表达式 (b + 1)
是一个整型。右操作数为int,左操作数提升为int,表达式为操作数提升后的类型。
来自 Java 语言规范,5.6.2. Binary Numeric Promotion:
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.
请注意,即使 两个 操作数都是短类型,也会发生最后一次提升。您无法避免使用 (b + (short) 1)
.
提升为 int
来自15.18.2. Additive Operators (+ and -) for Numeric Types
The type of an additive expression on numeric operands is the promoted type of its operands.
执行 +
会自动将 short
提升为 int
。这样做你就会看到溢出。
System.out.println("b+1: "+(short)(b+1)); //-32768
来自 Java 语言规范,5.6.2. Binary Numeric Promotion:
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.
注意最后一条规则,本质上这意味着即使它们都是short,它们也会被提升为int,这是无法避免的。
你可以:
short b= 32767;
short d= 12;
System.out.println("b+1: "+ (d+b)); // 32779
答案仍然有效。
1
是一个 int
文字。当您计算 b+1
时,您实际上将 b
提升为 int
,然后添加 1
,结果是 32768
,这是完全合法的 [=12] =] 值。如果您再次将其转换为 short
,您将看到预期的溢出 (-32768
):
System.out.println("b+1: " + (short)(b + 1));
正如其他人所指出的,加法将操作数提升为 int
。
请注意,+=
运算符会自动转换回 short
:
short b=32767;
System.out.println(b + 1); // 32768, because of integer promotion.
b += 1; // Equivalent to b = (short)(b + 1);
System.out.println(b); // -32768
b++;
/++b;
会产生与 b += 1
.
相同的结果
无需混淆,试试这个:
short b = 32767;
short c = b + 1;
你得到了什么?对,你得到:
error: incompatible types: possible lossy conversion from int to short
short c = b + 1;
那么,你的生产线上发生了什么?
System.out.println("b+1: "+(b+1));
?
好吧,b+1
对于 short
来说太大了,正如您所说的正确,但是在这里您向它添加了一个 int,使结果也成为一个 int。 32768 是一个有效的整数。
正如其他人已经指出的那样,如果您明确地将其转换为 (short)
,您就会得到您所要求的。
另一方面,这不适用于 short c = b + 1;
,因为这里声明的类型是短整型,而实际类型是 int
.
short c = (short) (b + 1);
解决了 "problem"
最近学习了二元制中表示正整数和负整数的补码法。然后,我尝试使用 java 和以下短代码来查看实际效果:
int a=2147483647;
System.out.println("a: "+a);
System.out.println("a+1: "+(a+1));
short b=32767;
System.out.println("b: "+b);
System.out.println("b+1: "+(b+1));
输出:
a: 2147483647
a+1: -2147483648
b: 32767
b+1: 32768
这让我很困惑,因为我认为 b+1,用二进制表示为 011111111111111,会变成 1000000000000000,或者用十进制表示 -32768。怎么回事?
虽然 b
是一个短整型,但表达式 (b + 1)
是一个整型。右操作数为int,左操作数提升为int,表达式为操作数提升后的类型。
来自 Java 语言规范,5.6.2. Binary Numeric Promotion:
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.
请注意,即使 两个 操作数都是短类型,也会发生最后一次提升。您无法避免使用 (b + (short) 1)
.
来自15.18.2. Additive Operators (+ and -) for Numeric Types
The type of an additive expression on numeric operands is the promoted type of its operands.
执行 +
会自动将 short
提升为 int
。这样做你就会看到溢出。
System.out.println("b+1: "+(short)(b+1)); //-32768
来自 Java 语言规范,5.6.2. Binary Numeric Promotion:
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.
注意最后一条规则,本质上这意味着即使它们都是short,它们也会被提升为int,这是无法避免的。
你可以:
short b= 32767;
short d= 12;
System.out.println("b+1: "+ (d+b)); // 32779
答案仍然有效。
1
是一个 int
文字。当您计算 b+1
时,您实际上将 b
提升为 int
,然后添加 1
,结果是 32768
,这是完全合法的 [=12] =] 值。如果您再次将其转换为 short
,您将看到预期的溢出 (-32768
):
System.out.println("b+1: " + (short)(b + 1));
正如其他人所指出的,加法将操作数提升为 int
。
请注意,+=
运算符会自动转换回 short
:
short b=32767;
System.out.println(b + 1); // 32768, because of integer promotion.
b += 1; // Equivalent to b = (short)(b + 1);
System.out.println(b); // -32768
b++;
/++b;
会产生与 b += 1
.
无需混淆,试试这个:
short b = 32767;
short c = b + 1;
你得到了什么?对,你得到:
error: incompatible types: possible lossy conversion from int to short short c = b + 1;
那么,你的生产线上发生了什么?
System.out.println("b+1: "+(b+1));
?
好吧,b+1
对于 short
来说太大了,正如您所说的正确,但是在这里您向它添加了一个 int,使结果也成为一个 int。 32768 是一个有效的整数。
正如其他人已经指出的那样,如果您明确地将其转换为 (short)
,您就会得到您所要求的。
另一方面,这不适用于 short c = b + 1;
,因为这里声明的类型是短整型,而实际类型是 int
.
short c = (short) (b + 1);
解决了 "problem"