这个问题原本是在上课的时候老师提出来的,但对于我这个新人来说,我还真的不太清楚这些有什么用处,对于二进制仅仅只是了解它是计算机的基本而已,而八进制与十六进制就一点也不清楚了,因此再次之后我搜索了一下他们的用途或者来历,总结了一下记录一下。
这篇文章主要是写了一些二进制中与位相关的运算操作,并简要的聊了一下八进制与十六进制。一般来说计算机的存储方式都是二进制。由于计算机内存的数据都是二进制,所以计算机在完成与二进制相关的位运算时会更加迅速,更加高效。
一、二进制
二进制是计算机存储数据的形式,逢二进一,所以是二进制。由于计算机内存中的数据都是以二进制的形式进行存储的,所以用位运算会大大提高计算机执行效率。提高程序性能。下面直接看一下二进制在代码里的相关应用。
一些位操作的符号:& | ^ ~ << >>
- 判断数字的奇偶,用number&1==0就可以知道能否被2整除
//1.判断数字奇偶性
int number = sc.nextInt();
if (number % 2 == 0) {
System.out.println("偶数");
} else {
System.out.println("奇数");
}
//用位操作来实现
int number = sc.nextInt();
if ((number & 1) == 0) {
System.out.println("偶数");
} else {
System.out.println("奇数");
}
这两种方法本质上都是判断最后一位能否被二整除,后一种只是判断他的二进制第一位是否为1,若为1则代表为奇数。
-
用^交换两个数字
基本的用中间值,去交换两个数字
//2.交换两个数字
System.out.print("number1: ");
int number1 = sc.nextInt();
System.out.print("number2: ");
int number2 = sc.nextInt();
/*中间变量交换*/
int temp;
temp = number1;
number1 =number2;
number2 = temp;
System.out.println("number1: "+number1);
System.out.println("number2: "+number2);
这里是用位操作来实现
//用位操作来实现
System.out.print("number1: ");
int number1 = sc.nextInt();
System.out.print("number2: ");
int number2 = sc.nextInt();
/*异或*/
number1^=number2;
number2^=number1;
number1^=number2;
System.out.println("number1: "+number1);
System.out.println("number2: "+number2);
用位操作来实现的交换,不需要中间变量,可以直接交换。但是代码的可读性不太好,不知道的人可能根本看不懂。但这就是所谓的高级呗。可以不用但最起码得知道。
- 得到一个数字的相反数
先看正常的
//3.数的相反数
System.out.print("相反数-number: ");
int number = sc.nextInt();
number = -number;
System.out.println("number: " + number);
再试试特别的
//特别的
System.out.print("相反数-number: ");
int number = sc.nextInt();
number = ~number+1;
System.out.println("number: " + number);
源码除符号位按位取反再加1得到补码,通过这个逻辑,如果全部取反(包括符号位)再加1,就可以实现正负的转换
同理可以得到一个数的绝对值,只需要先判断一下首位,也就是符号位是否1还是0就可以了。number>>31
表示把二进制数向右移动31位,即把首位移动到第一位的位置上。再通过&1
运算就可以去取出符号位。若符号位位1(代表为负数),就返回它的相反数。
//4.数的绝对值
System.out.print("绝对值-number: ");
int number = sc.nextInt();
number = (number>>31&1)==0?number:~number+1;
System.out.println("number: " + number);
- 用&在内存位上对同一个事物进行多次的判断,感觉这个的实用性很好。如管理权限,属性的种类。就仅仅对于一个容器int,可以有4X8=32个位置进行判断(32bit)
//人 类
public class Person {
String name;
int age;
int property;
public Person() {
}
public Person(String name, int age, int property) {
this.name = name;
this.age = age;
this.property = property;
}
}
//属性 类
public class Property{
//标签
static int 有命 = 1;
static int 有钱 = 1 << 1;
static int 有女朋友 = 1 << 2;
}
//主入口
public class Text {
public static void main(String[] args) {
//用每一位表示一个属性
Person 张三 = new Person("张三", 23, Property.有命 | Property.有钱);//张三有命并且有钱
if ((张三.property & Property.有女朋友) != 0) {
System.out.println(张三.name + "有女朋友");
} else {
System.out.println(张三.name + "没有女朋友");
}
}
}
以上代码中定义了int property
中的第一个二进制位(最右边的位)是"有命"这个属性,同样第二个是"有钱"的属性,以此类推。
最终定义Person 张三
这个属性的时候给他赋值了Property.有命 | Property.有钱
,用|运算将两个‘有’的属性合并起来。而最终问他有没有女朋友,是问他的第三个二进制位上是个否有1,即用"100"去按位与上int property
。就是这样了,至于结果我就不知道。
再来简单的说一下其他两个,主要就是帮助我们辅助记忆或者有一些特殊的用途:
二、八进制
1个八进制数可以表示3个二进制数字,8=2的3次方
八进制在实际运算中没有什么特殊的应用,应用范围很少,我所知道的主要用于编码形式,如西门子S7-200系列的PLC,输入I和输出O的编号都是从0.0到15.7,小数部分采用八进制编码。八进制基本已经被淘汰,主要用于一些12位、24位以及36位的计算机。
三、十六进制
十六进制的应用还是挺广泛的,主要就是被作为一种二进制的记忆工具。因为一个十六进制数可以表示4个二进制数,16=2的4次方。
应用有
-
RGB色彩的16进制常量方便书写
如:红色#FF0000;绿色#00FF00;蓝色#0000FF
-
有时候我们会希望用一个位置去存储大于9的数字;
比如要求用一个字符表示9以上的数字可以用ABC... 表示
以及用来设置一些特殊的值,二进制中全为1的或者是其他的一些;0xFFFFFF表示二进制中全位为1的数。
内存的存储地址用两个16进制数就可以方便表示,方便记忆。记个C4,总比记个1100 0100好吧。比如还有ipv6的地址格式,为32个16进制数。本身就不太好记换二进制,十进制就更让人头疼了。