Java Programming 【Chapter 2_QA】

1、大端序(Big Endian)、小端序(Little Endian)的概念理解、举例说明。

什么是大端序和小端序?

  • 端序(Endianness)是指计算机系统中多字节数据(如整数)在内存中的存储顺序。
  • 大端序(Big Endian)高位字节(数值较大的部分)存储在低地址低位字节存储在高地址,像是“从左到右”读数,类似我们日常书写习惯。
  • 小端序(Little Endian)低位字节存储在低地址高位字节存储在高地址,像是“从右到左”读数,计算机更常使用这种方式优化计算。

通俗类比

想象一个三位数“123”要写在纸上:

  • 大端序:像正常书写,先写“1”(高位)在左边,再写“2”“3”(低位)向右,像“123”。
  • 小端序:像倒着写,先写“3”(低位)在左边,再写“2”“1”(高位)向右,像“321”,但实际读时要反过来理解。

举例说明

假设一个 16 位整数 0x1234(十六进制,十进制 4660),用 2 个字节表示:

  • 内存地址:从 0x100 开始,占 2 字节(0x100 和 0x101)。
  • 大端序
    • 0x100 存高位字节 0x12。
    • 0x101 存低位字节 0x34。
    • 内存:12 34,读出来是 0x1234。
  • 小端序
    • 0x100 存低位字节 0x34。
    • 0x101 存高位字节 0x12。
    • 内存:34 12,读出来仍需解释为 0x1234。

为什么有区别?

  • 硬件优化小端序便于处理器直接处理低位数据(如加减法),常见于 Intel x86 架构。
  • 网络传输大端序常用于网络协议(如 TCP/IP),因为它更直观,类似人类阅读习惯。
  • 兼容性:不同系统可能采用不同端序,需转换(如 UTF-16 Big/Little Endian)。

红框内容中的应用

  • UTF-16 Big Endian:Unicode 字符用 2 字节存储,高位字节先存(如 0x9A6C 存为 9A 6C)。
  • UTF-16 Little Endian:低位字节先存(如 0x9A6C 存为 6C 9A)。
  • BOM(字节顺序标记):文件开头可能加特殊字节(如 FE FF 表示 Big Endian)帮助识别端序。

重点总结

  • 大端序:高位在前,像“123”,适合人类阅读。
  • 小端序:低位在前,像“321”但反读,优化计算。
  • 区别:存储顺序相反,影响数据解释,需根据上下文(硬件或协议)选择。

 

2、在 Java 中,有哪些位移运算?例如 左移 <<, 右移 >> 有符号左移,无符号左移,有符号右移,无符号右移?

在 Java 中,位移运算符用于对整数的二进制表示进行位操作。以下是常见的位移运算符及其概念、区别,并通过举例说明。


位移运算符及概念

  1. 左移运算符 <<
    • 概念:将操作数的二进制位向左移动指定位数,低位补 0,高位溢出被丢弃。
    • 特性:相当于将数字乘以 2^n(n 为移位数),但可能溢出。
    • 适用范围:对所有整数类型(int、long 等)。
  2. 有符号右移运算符 >>
    • 概念:将操作数的二进制位向右移动指定位数,保留符号位(正数补 0,负数补 1),低位溢出被丢弃。
    • 特性:相当于将数字除以 2^n 并向下取整,保持符号。
    • 适用范围:对有符号整数(int、long)。
  3. 无符号右移运算符 >>>
    • 概念:将操作数的二进制位向右移动指定位数,高位统一补 0,低位溢出被丢弃。
    • 特性:将负数转为正数,相当于逻辑右移,忽略符号。
    • 适用范围:对所有整数类型。
  4. 无符号左移
    • 注意:Java 中没有专门的“无符号左移”运算符,<< 对所有整数都按相同方式操作(低位补 0),符号无关。

区别

  • 符号处理
    • <<:不考虑符号,仅左移补 0。
    • >>:考虑符号,补符号位(0 或 1)。
    • >>>:不考虑符号,始终补 0。
  • 溢出行为
    • <<:高位溢出可能改变符号。
    • >> 和 >>>:低位溢出被丢弃。
  • 用途
    • <<:乘法优化。
    • >>:带符号的除法优化。
    • >>>:无符号数处理或位操作。

举例说明

假设使用 int 类型,初始值 a = 12(二进制 00001100,32 位补齐高位 0)。

1. 左移 <<

int a = 12;
int b = a << 2; // 左移 2 位
System.out.println(b); // 输出 48
  • 过程00001100 左移 2 位成 00110000(十进制 48)。
  • 解释:相当于 12×22=12x2^2=48,低位补 0,高位溢出。

2. 有符号右移 >>

int a = 12;
int b = a >> 2; // 右移 2 位
System.out.println(b); // 输出 3
  • 过程00001100 右移 2 位成 00000011(十进制 3)。
  • 解释:相当于 12÷2^2=3,高位补 0(正数)。

3. 有符号右移(负数示例)

int a = -12; // 二进制补码 11111111 11111111 11111111 11110100
int b = a >> 2; // 右移 2 位
System.out.println(b); // 输出 -3
  • 过程11110100 右移 2 位成 11111101(补 1,因负数),十进制 -3。
  • 解释:保持符号,相当于 −12÷4=3。

4. 无符号右移 >>>

int a = -12; // 二进制补码 11111111 11111111 11111111 11110100
int b = a >>> 2; // 无符号右移 2 位
System.out.println(b); // 输出 1073741821
  • 过程:11110100 右移 2 位成 00111101(高位补 0),补齐 32 位为 00111111 11111111 11111111 11111101,十进制 1073741821。
  • 解释:忽略符号,转换为正数。

5. 无符号左移(使用 <<)

int a = 12;
int b = a << 2; // 左移 2 位
System.out.println(b); // 输出 48
int c = -12 << 2; // 负数左移
System.out.println(c); // 输出 -48
  • 过程-12 的补码左移 2 位,高位溢出,保持负数。
  • 解释<< 对正负数行为一致,仅补 0。

总结表

 
运算符补位规则符号影响典型用途
<< 低位补 0 乘以 2^n
>> 补符号位 (0/1) 除以 2^n (带符号)
>>> 高位补 0 无符号右移
 

注意

  • 移位次数超过类型位数(32 位 int)会取模(例如 << 34 相当于 << 2)。
  • 负数补码需理解二进制表示,>>> 常用于位掩码或无符号转换。

 

3、如何理解上述左移<<的如下计算结果?

int c = -12 << 2; // 负数左移
System.out.println(c); // 输出 -48

1. 理解负数 -12 的二进制表示

  • Java 使用 补码(Two's Complement)表示有符号整数。
  • int 类型是 32 位,-12 的二进制表示需要从正数 12 开始计算:
    • 正数 12 的二进制:00001100(低 8 位,32 位高位补 0)。
    • 补码计算:
      • 取反:11110011(对每位取反)。
      • 加 1:11110100(加上 1)。
    • 因此,-12 的 32 位补码是:11111111 11111111 11111111 11110100。
    • 符号位:最高位 1 表示负数。

2. 左移运算 << 2

  • 左移规则<< 将二进制位向左移动指定位数(这里是 2 位),低位补 0,高位溢出被丢弃。
  • -12 的补码 11111111 11111111 11111111 11110100 左移 2 位:
    • 原数:11111111 11111111 11111111 11110100
    • 左移 2 位:11111111 11111111 11111111 11010000(低位补 2 个 0,高位 2 位溢出)。
  • 结果:新的 32 位二进制数 11111111 11111111 11111111 11010000。

3. 转换为十进制

  • 这一串二进制是补码形式,需转换为十进制:
    • 符号位 1 表示负数,取反加 1 还原。
    • 取反:00000000 00000000 00000000 00101111。
    • 加 1:00000000 00000000 00000000 00110000 = 48(十进制)。
    • 负数值:-48。
  • 验证:-12 << 2 相当于 12×4=48,与计算一致。

4. 为什么是 -48?

  • 左移效果<< 2 相当于乘以 2^2 =4。对于正数 12 << 2 = 48,负数 -12 << 2 保持符号,变为 -48。
  • 补码特性:左移不改变符号位(最高位仍为 1),只是扩展了数值幅度,负数变“更负”。

简图说明

初始 (-12): 1111 1111 1111 1111 1111 1111 1111 0100
左移 2 位:  1111 1111 1111 1111 1111 1111 1101 0000
结果 (-48): 保持符号位 1,低位补 0。

总结

  • -12 << 2 的结果是 -48,因为:
    1. -12 的补码左移 2 位,得到 11111111 11111111 11111111 11010000。
    2. 补码转换为十进制,符号位 1 表示负数,值是 -48。
    3. 数学上,-12 x 4 = -48,与位运算结果一致。
  • 关键点:左移保持符号,负数左移加倍负值幅度。

 

posted @ 2025-06-28 16:08  AlphaGeek  阅读(21)  评论(0)    收藏  举报