Java 中如何表示负数,有符号和无符号的区别,补码的计算规则,char byte short int long 的范围

Java 中如何表示负数,有符号和无符号的区别,补码的计算规则,char byte short int long 的范围

char、byte、short 最大值

类型 位数 最大值(十进制) 最大值(十六进制)
char 16 位无符号 65535 0xFFFF / \uFFFF
byte 8 位有符号 127 0x7F
short 16 位有符号 32767 0x7FFF

对应关系可以这样理解:

  • char :无符号 16 位,范围是 0x0000 ~ 0xFFFF,最大值是 0xFFFF。
  • byte :有符号 8 位,范围是 -128 ~ 127,最大值是 0x7F。
  • short :有符号 16 位,范围是 -32768 ~ 32767,最大值是 0x7FFF。

为什么 byte、short 是有符号

byte、short 是整数类型,Java 统一按有符号补码设计;char 不是普通整数,而是 16 位 Unicode 码元,所以必须无符号。

Java 的 byte、short、int、long 都采用二进制补码表示,最高位是符号位。

类型 位数 取值范围
byte 8 位 -128 ~ 127
short 16 位 -32,768 ~ 32,767
int 32 位 -2,147,483,648 ~ 2,147,483,647
long 64 位 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

补码怎么表示负数

规则很简单:

  1. 正数:补码 = 原码。
  2. 负数:先写出对应正数的二进制,再按位取反,最后加 1。

以 8 位 byte 为例:

十进制 步骤 二进制
+3 正数原样 0000 0011
-3 0000 0011 取反 → 1111 1100,再加 1 1111 1101
-1 0000 0001 取反 → 1111 1110,再加 1 1111 1111
-128 特殊最小值 1000 0000

所以 byte 的范围是 -128 ~ 127,而不是对称的 -127 ~ 127。因为补码里 0 只占一个编码,负数那边就多出一个位置,于是最小负数比最大正数多 1。

为什么一定要用一位做符号位

计算机里只有 0 和 1,没有"+"和"-"这两个符号。要表示负数,就必须把"正负"这个信息也编码进二进制里。

最直观的做法就是拿最高位当符号位 :0 表示正,1 表示负。

8位二进制 无符号解读 有符号解读(补码)
0111 1111 127 +127
1000 0000 128 -128
1111 1111 255 -1

那为什么"牺牲"了正数范围?

以 8 位为例,256 个编码要分给正数、负数和零。补码的分配是:

  • 1 个 给零(0000 0000)
  • 127 个 给正数(0000 0001 ~ 0111 1111)
  • 128 个 给负数(1000 0000 ~ 1111 1111)

所以正数最大只有 127,而负数最小能到 -128。负数多一个,是因为零只占一个编码(不像原码有 +0 和 -0 两个),省下来的那个编码就归了负数。

用这一位换来了什么

  • 减法变加法:a - b 等价于 a + (-b),CPU 只需要加法器,不需要单独的减法电路。
  • 符号位参与运算:符号位和普通位一视同仁,不需要特殊判断。
  • 零唯一:避免了 +0 和 -0 的歧义。

简单说:不是"浪费",而是"交易" ------用一半的正数范围,换来了负数表达能力和硬件运算的极大简化。如果不需要负数,直接用无符号类型(如 char)就好,那 16 位就能完整表示 0~65535。

举一个补码进行加法计算的例子

用一个 8 位 byte 的例子:计算 15 + (-25)。

1. 先写出两个数的补码

15 是正数,正数补码 = 原码:

text 复制代码
15 的原码:0000 1111
15 的补码:0000 1111

-25 是负数,补码 = 对应正数按位取反再加 1:

text 复制代码
25 的原码:  0001 1001
按位取反:  1110 0110
加 1:      1110 0111

所以:

text 复制代码
-25 的补码:1110 0111

2. 两个补码直接相加

text 复制代码
  0000 1111   (15 的补码)
+ 1110 0111   (-25 的补码)
-----------
  1111 0110

最高位没有产生额外进位,所以直接保留 1111 0110。

3. 把结果补码还原成原码

1111 0110 最高位是 1,说明它是负数的补码。还原方法:减 1,再按位取反。

text 复制代码
1111 0110 - 1 = 1111 0101
按位取反:    0000 1010

所以结果是:

text 复制代码
-10

验证:

text 复制代码
15 + (-25) = -10 ✅

这个例子说明了什么

  • 符号位也参与运算,不需要单独判断正负。
  • 减法被统一成加法 :15 + (-25) 就是两个补码相加。
  • 如果最高位产生进位,在固定位宽下直接丢弃。比如 4 位里 5 + (-2):0101 + 1110 = 1 0011,丢弃进位后得到 0011,也就是 3。

要不要说说补码溢出的判断条件?比如什么情况下结果会"绕回来"变成错误值。

相关推荐
weixin_307779131 小时前
C++代码实现MATLAB中的fitrtree函数功能
开发语言·c++·算法·matlab
奇牙coding1 小时前
Codex CLI 升级后多文件编辑静默失效:config.yaml 枚举变更排查与修复指南
java·前端·javascript·ai
爱读书的小胖1 小时前
Codewars:Rot13(C)解题分析
c语言·开发语言
小羊没烦恼!2 小时前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
鸽鸽程序猿2 小时前
【项目】【在线判题系统】b端题目增删改
开发语言·python
Lhappy嘻嘻2 小时前
读懂 JVM:内存模型、类加载机制、分代回收
java·开发语言·jvm
黄俊懿2 小时前
【架构师从入门到进阶】第六章:服务集群优化——第八节:线程数公式
java·服务器·数据库·分布式·性能优化·架构·系统架构
Rain的Java大神之路2 小时前
别再死磕 MySQL 了:向量数据库与 RAG 生产落地实录(Java 工程师专场)
java·后端·面试
七夜zippoe2 小时前
Spring AI 是什么?Java 工程师的 AI 开发第一站
java·人工智能·spring·ai·开发