Java基础快速入门:进制、位运算与数组操作

本文纲要

  1. 进制介绍与Java书写格式
  2. 任意进制转十进制
  3. 十进制转任意进制
  4. 快速进制转换法(8421码)
  5. 原码、反码、补码
  6. 位运算 - 基本位运算符
  7. 位运算 - 位移运算符
  8. 案例:数据交换
  9. 案例:数组反转

进制介绍与Java书写格式

计算机底层使用二进制进行运算与存储,但在开发中我们也会接触到八进制、十进制、十六进制。
掌握这些进制及它们在Java中的书写方式,有助于理解底层原理。

进制规则Java书写格式
十进制逢十进一,借一当十,默认数值类型直接书写,如 10
二进制逢二进一,借一当二,只有 0 和 10b 开头,如 0b10,b 大小写均可
八进制逢八进一,借一当八0 开头,如 010
十六进制逢十六进一,借一当十六,用 0-9 和 a-f 表示0x 开头,如 0x10,x 大小写均可

注意事项

  • 上述进制标识从 JDK7 开始支持。
  • 控制台打印时,无论代码中书写何种进制,最终展示的都是 十进制 数值。

示例

// Demo1.java 
package com.wb.demo;
 
public class Demo1 {
    public static void main(String[] args) {
        System.out.println(10);
        System.out.println("二进制数据0b10的十进制表示为:" + 0b10);   // 2 
        System.out.println("八进制数据010的十进制表示为:" + 010);     // 8 
        System.out.println("十六进制数据0x10的十进制表示为:" + 0x10); // 16 
    }
}

任意进制转十进制

1 )公式

系数 × 基数^权次幂 再求和

  • 系数:每一位上的数字
  • 基数:当前进制的基,如二进制基数是2,十六进制是16
  • 权:从数字最右边开始,编号为0,依次向左递增
  • 再求和: 各项结果相加

示例:二进制 0b100 转十进制

系数基数权次幂计算结果
1221×2²=4
0210
0200

求和:4 + 0 + 0 = 4

示例:十六进制 0x100 转十进制

系数基数权次幂计算结果
11621×16²=256
01610
01600

求和:256。

该公式适用于 任意进制转十进制。

十进制转任意进制

公式:除基取余,商为0时停止,余数倒序排列。

示例:十进制 11 转二进制

除基余数
11÷251
5÷221
2÷210
1÷201

余数倒序:1011,所以 11(10) = 1011(2)

示例:十进制 60 转十六进制

除基余数
60÷16312©
3÷1603

余数倒序:3C,所以 60(10) = 0x3C

快速进制转换法(8421码)

1 ) 8421码(BCD代码)

将二进制每一位对应的固定值记下,直接累加即可快速得到十进制值

二进制位权重1286432168421
对应二进制位b7b6b5b4b3b2b1b0
  • 二进制位为 1 时,取该位权重并相加;为 0 则忽略

2 ) 二进制转十进制示例

  • 二进制: 0b 1 1 0 1
  • 权重: 8 4 2 1
  • 取1的位: 8 + 4 + 1 = 13

3 ) 二进制转八进制

将二进制从右向左每 3位 一组(因为八进制最大为7,3位二进制最大为7),每组按8421码求和,结果拼在一起。

二进制: 0b 11 1100
分组: 011 110 (补零对齐)
8421: 0+2+1=3 4+2+0=6
八进制: 36

Java中没有直接的八进制转换API,但此方法适合手算理解。

4 ) 二进制转十六进制

每 4位 一组(十六进制最大为15),每组求和,大于9的用字母表示。

二进制: 0b 11 1100
分组: 0011 1100
8421: 2+1=3 8+4=12 → C
十六进制: 3C

原码、反码、补码

计算机中的数据以 二进制补码 形式运算,而原码用来直观查看数值大小,反码是转换过程的中间状态。

  • 原码:最高位为符号位(0正1负),其余位表示数值。
  • 反码:正数的反码等于原码;负数反码为原码除符号位外按位取反。
  • 补码:正数的补码等于原码;负数补码为反码末位加一。

示例:int 强转为 byte 的解释

Java中 int 占4字节,byte 占1字节。将 130 强转为 byte 会发生精度损失,结果为 -126。

过程如下:

  1. 130int 原码(补码相同,正数):
    00000000 00000000 00000000 10000010
  2. 强转为 byte 截取低8位:10000010 (此时已是补码,且符号位为1,表示负数)
  3. 补码求原码:
    补码减1得反码:10000001
    反码取反(符号位不变)得原码:11111110
    原码对应的十进制:-(2+4+8+16+32+64) = -126

位运算 - 基本位运算符

位运算符直接对整数的二进制位操作,运算速度快。二进制位中,1 表示 true,0 表示 false。

运算符名称运算规则
&位与全1才1(有0则0)
`位或有1则1
^位异或相同为0,不同为1
~取反所有位(含符号位)0变1,1变0

示例代码

// Demo2.java 
package com.wb.demo;
 
public class Demo2 {
    public static void main(String[] args) {
        System.out.println(6 & 2);   // 2 
        System.out.println(~6);      // -7 
    }
}

运算过程分析

6 & 2:

   00000000 00000000 00000000 00000110  (6)`
&  00000000 00000000 00000000 00000010  (2)`
-----------------------------------------
   00000000 00000000 00000000 00000010  → 2

~ 6:

  00000000 00000000 00000000 00000110  (6 的补码)
~ 11111111 11111111 11111111 11111001  (取反后仍为补码)

得到的是负数的补码,反推原码:

补码减 1 :             11111111 11111111 11111111 11111000 (反码)
反码取反(符号位不变):    10000000 00000000 00000000 00000111 → -7

位运算 - 位移运算符

运算符名称运算规律
<<有符号左移左移 n 位相当于乘 2^n,右侧补 0
>>有符号右移右移 n 位相当于除 2^n,左侧补符号位
>>>无符号右移右移 n 位,左侧一律补 0(很少使用)

示例代码

// Demo3.java 
package com.wb.demo;
 
public class Demo3 {
    public static void main(String[] args) {
        System.out.println(12 << 1);  // 24 
        System.out.println(12 << 2);  // 48 
    }
}

12 << 2 运算过程:

12 二进制(补零至8位示意): 00001100
左移2位: 00110000 → 十进制 48

符号位丢弃,右侧补 0

案例:数据交换

1 ) 方式一:使用临时变量

最常用、最易读的交换方式

// Test1.java 
package com.wb.test;
 
public class Test1 {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
 
        int temp = a;
        a = b;
        b = temp;
 
        System.out.println("a=" + a);  // 20 
        System.out.println("b=" + b);  // 10 
    }
}

2 ) 方式二:利用异或运算
利用异或特性:一个数异或另一个数两次,结果不变

// Test1_1.java 
package com.wb.test;
 
public class Test1_1 {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
 
        a = a ^ b;
        b = a ^ b;   // b = (a^b) ^ b = a 
        a = a ^ b;   // a = (a^b) ^ a = b 
 
        System.out.println("a=" + a);
        System.out.println("b=" + b);
    }
}

验证异或特性的例子

// Demo4.java 
package com.wb.demo;
 
public class Demo4 {
    public static void main(String[] args) {
        System.out.println(10 ^ 5 ^ 10); // 结果还是 5 
    }
}

实际开发建议使用临时变量方式,异或方式多出现在面试题中

案例:数组反转

需求:将数组 {19, 28, 37, 46, 50} 反转为 {50, 46, 37, 28, 19}

核心思路

使用 双指针 分别指向数组首尾,交换元素后指针向中间移动,直到指针相遇

1 ) 第一步:手动交换首尾元素(理解基础)

// Test2_2.java 
package com.wb.test;
 
public class Test2_2 {
    public static void main(String[] args) {
        int[] arr = {11, 22, 33, 44, 55};
        // 交换 arr[0] 和 arr[4]
        int temp = arr[0];
        arr[0] = arr[4];
        arr[4] = temp;
 
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

2 )第二步:使用循环完成整个反转

// Test2.java 
package com.wb.test;
 
public class Test2 {
    public static void main(String[] args) {
        int[] arr = {19, 28, 37, 46, 50};
        // 双指针 
        int start = 0;
        int end = arr.length - 1;
 
        // 当 start < end 时进行交换 
        for ( ; start < end; start++, end--) {
            int temp = arr[start];
            arr[start] = arr[end];
            arr[end] = temp;
        }
 
        // 遍历输出反转后的数组 
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

3 ) 循环的另一种紧凑写法(在 for 初始化中定义双指针):

for(int start = 0, end = arr.length - 1; start < end; start++, end--) {
    int temp = arr[start];
    arr[start] = arr[end];
    arr[end] = temp;
}

总结

本文介绍了Java中常见的进制表示与转换、原反补码的运作原理以及位运算、位移运算,并结合经典案例“数据交换”和“数组反转”加深理解。

这些基础知识是理解Java底层运算和阅读源码的重要铺垫。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值