java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java进制、位运算与数组

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

作者:Wang's Blog

本文详细介绍了Java中不同进制(二、八、十、十六进制)的表示与转换,强调了原码、反码、补码的概念及其在计算机运算中的应用,并通过数据交换和数组反转案例,深入解析了位运算和位移运算的规则与实际应用,感兴趣的朋友一起看看吧

进制介绍与Java书写格式

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

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

注意事项

示例

// 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 )公式

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

示例:二进制 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

2 ) 二进制转十进制示例

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

原码、反码、补码

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

示例: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底层运算和阅读源码的重要铺垫。

到此这篇关于Java基础快速入门教程之进制、位运算与数组操作的文章就介绍到这了,更多相关java进制、位运算与数组内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文