详谈Java中的二进制及基本的位运算

二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。计算机中的二进制则是一个非常微小的开关,用“开”来表示1,“关”来表示0。

那么Java中的二进制又是怎么样的呢?让我们一起来揭开它神秘的面纱吧。

一、Java内置的进制转换

有关十进制转为二进制,和二进制转为十进制这种基本的运算方法这里就不展开讲了。

在Java中内置了几个方法来帮助我们进行各种进制的转换。如下图所示(以Integer整形为例,其他类型雷同):

1,十进制转化为其他进制:

二进制:Integer.toHexString(int i);
八进制:Integer.toOctalString(int i);
十六进制:Integer.toBinaryString(int i);

2,其他进制转化为十进制:

二进制:Integer.valueOf("0101",2).toString;
八进制:Integer.valueOf("376",8).toString;
十六进制:Integer.valueOf("FFFF",16).toString;

3,使用Integer类中的parseInt()方法和valueOf()方法都可以将其他进制转化为10进制。

不同的是parseInt()方法的返回值是int类型,而valueOf()返回值是Integer对象。

二、基本的位运算

二进制可以和十进制一样加减乘除,但是它还有更简便的运算方式就是——位运算。比如在计算机中int类型的大小是32bit,可以用32位的二进制数来表示,所以我们可以用位运算来对int类型的数值进行计算,当然你也可以用平常的方法来计算一些数据,这里我主要为大家介绍位运算的方法。我们会发现位运算有着普通运算方法不可比拟的力量。更多位运算应用请转移到我下篇博文《神奇的位运算》

首先,看一下位运算的基本操作符:

优点:

特定情况下,计算方便,速度快,被支持面广
如果用算数方法,速度慢,逻辑复杂
位运算不限于一种语言,它是计算机的基本运算方法

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

(一)按位与&

两位全为1,结果才为1

0&0=0;0&1=0;1&0=0;1&1=1

例如:51&5 即0011 0011 & 0000 0101 =0000 0001 因此51&5=1.

特殊用法

(1)清零。如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都是零的数值相与,结果为零。

(2)取一个数中指定位。

例如:设X=10101110,取X的低四位,用X&0000 1111=0000 1110即可得到。

方法:找一个数,对应x要取的位,该数的对应位为1,其余位为零,此数与x进行“与运算”可以得到x中的指定位。

(二)按位或 |

只要有一个为1,结果就为1。

0|0=0; 0|1=1;1|0=1;1|1=1;

例如:51|5 即0011 0011 | 0000 0101 =0011 0111 因此51|5=55

特殊用法

常用来对一个数据的某些位置1。

方法:找到一个数,对应x要置1的位,该数的对应位为1,其余位为零。此数与x相或可使x中的某些位置1。

(三)异或 ^

两个相应位为“异”(值不同),则该位结果为1,否则为0

0^0=0; 0^1=1; 1^0=1; 1^1=0;

例如:51^5 即0011 0011 ^ 0000 0101 =0011 0110 因此51^5=54

特殊用法

(1) 与1相异或,使特定位翻转

方法:找一个数,对应X要翻转的位,该数的对应为1,其余位为零,此数与X对应位异或即可。

例如:X=1010 1110,使X低四位翻转,用X^0000 1111=1010 0001即可得到。

(2) 与0相异或,保留原值

例如:X^0000 0000 =1010 1110

(3)两个变量交换值

1.借助第三个变量来实现

C=A;A=B;B=C;

2.利用加减法实现两个变量的交换

A=A+B;B=A-B;A=A-B;

3.用位异或运算来实现,也是效率最高的

原理:一个数异或本身等于0 ;异或运算符合交换律

A=A^B;B=A^B;A=A^B

(四)取反与运算~

对一个二进制数按位取反,即将0变为1,1变0

~1=0 ;~0=1

(五)左移<<

将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)

例如: 2<<1 =4 10<<1=100

若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。

例如:

11(1011)<<2= 0010 1100=22

11(00000000 00000000 00000000 1011)整形32bit

(六)右移>>

将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。若右移时舍高位不是1(即不是负数),操作数每右移一位,相当于该数除以2。

左补0还是补1得看被移数是正还是负。

例如:4>>2=4/2/2=1

-14(即1111 0010)>>2 =1111 1100=-4

(七)无符号右移运算>>>

各个位向右移指定的位数,右移后左边空出的位用零来填充,移除右边的位被丢弃。

例如:-14>>>2

(即11111111 11111111 11111111 11110010)>>>2

=(00111111 11111111 11111111 11111100)=1073741820

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

上述提到的负数,他的二进制位表示和正数略有不同,所以在位运算的时候也与正数不同。

负数以其正数的补码形式表示!

以上述的-14为例,来简单阐述一下原码、反码和补码。

原 码

一个整数按照绝对值大小转化成的二进制数称为原码

例如:00000000 00000000 00000000 00001110 是14的原码。

反 码

将二进制数按位取反,所得到的新二进制数称为原二进制数的反码。

例如:将00000000 00000000 00000000 00001110 每一位取反,

得11111111 11111111 11111111 11110001

注意:这两者互为反码

补 码

反码加1称为补码

11111111 11111111 11111111 11110001 +1=

11111111 11111111 11111111 11110010

现在我们得到-14的二进制表示,现在将它左移

-14(11111111 11111111 11111111 11110010)<<2 =

11111111 11111111 11111111 11001000

=?

分析:这个二进制的首位为1,说明是补码形式,现在我们要将补码转换为原码(它的正值)

跟原码转换为补码相反,将补码转换为原码的步骤:

补码减1得到反码:(11000111)前24位为1,此处省略
反码取反得到原码(即该负数的正值)(00111000)
计算正值,正值为56
取正值的相反数,得到结果-56
结论:-14<<2 = -56

三、Java中进制运算

Java中二进制用的多吗?

平时开发中“进制转换”和“位操作”用的不多,Java处理的是高层。

在跨平台中用的较多,如:文件读写,数据通信。

来看一个场景:

如果客户机和服务器都是用Java语言写的程序,那么当客户机发送对象数据,我们就可以把要发送的数据序列化seriapzable,服务器端得到序列化的数据之后就可以反序列化,读出里面的对象数据。

随着客户机访问量的增大,我们不考虑服务器的性能,其实一个可行的方案就是把服务器的Java语言改成C语言。

C语言作为底层语言,反映速度都比Java语言要快,而此时如果客户端传递的还是序列化的数据,那么服务器端的C语言将无法解析,怎么办呢?我们可以把数据转为二进制(0,1),这样的话服务器就可以解析这些语言。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Java中基本数据类型有以下四种:

Int数据类型:byte(8bit,-128~127)、short(16bit)、int(32bit)、long(64bit)

float数据类型:单精度(float,32bit ) 、双精度(double,64bit)

boolean类型变量的取值有true、false(都是1bit)

char数据类型:unicode字符,16bit

对应的类类型:

Integer、Float、Boolean、Character、Double、Short、Byte、Long

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

(一)数据类型转为字节

例如:int型8143(00000000 00000000 00011111 11001111)

=>byte[] b=[-49,31,0,0]

第一个(低端)字节:8143>>0*8 & 0xff=(11001111)=207(或有符号-49)

第二个(低端)字节:8143>>1*8 &0xff=(00011111)=31

第三个(低端)字节:8143>>2*8 &0xff=00000000=0

第四个(低端)字节:8143>>3*8 &0xff=00000000=0

我们注意到上面的(低端)是从右往左开始的,那什么是低端呢?我们从大小端的角度来说明。

小端法(pttle-Endian)

低位字节排放在内存的低地址端即该值的起始地址,高位字节排位在内存的高地址端

大端法(Big-Endian)

高位字节排放在内存的低地址端即该值的起始地址,低位字节排位在内存的高地址端

为什么会有大小端模式之分呢?

这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

例如:32bit的数0x12 34 56 78(十二进制)

在Big-Endian模式CPU的存放方式(假设从地址0x4000开始存放)为


内存地址


0x4000


0x4001


0x4002


0x4003


存放内容


0x78


0x56


0x34


0x12

在pttle-Endian模式CPU的存放方式(假设从地址0x4000开始存放)为


内存地址


0x4000


0x4001


0x4002


0x4003


存放内容


0x12


0x34


0x56


0x78

(二)字符串转化为字节

1.字符串->字节数组

String s;
byte[] bs=s.getBytes();

2.字节数组->字符串

Byte[] bs=new byte[int];
String s =new String(bs);或
String s=new String(bs,encode);//encode指编码方式,如utf-8

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

两种类型转化为字节的方法都介绍了,下面写个小例子检验一下:

pubpc class BtyeTest {
 /*
 * int整型转为byte字节
 */
 pubpc static byte[] intTOBtyes(int in){
 byte[] arr=new byte[4];
 for(int i=0;i<4;i++){
  arr[i]=(byte)((in>>8*i) & 0xff);
 }
 return arr;
 }
 /*
 * byte字节转为int整型
 */
 pubpc static int bytesToInt(byte[] arr){
 int sum=0;
 for(int i=0;i<arr.length;i++){
  sum+=(int)(arr[i]&0xff)<<8*i;
 }
 return sum;
 }
 pubpc static void main(String[] args) {
 // TODO Auto-generated method stub
 byte[] arr=intTOBtyes(8143);
 for(byte b:arr){
  System.out.print(b+" ");
 }
 System.out.println();
 System.out.println(bytesToInt(arr));

 //字符串与字节数组
 String str="云开的立夏de博客园";
 byte[] barr=str.getBytes();

 String str2=new String(barr);
 System.out.println("字符串转为字节数组:");
 for(byte b:barr){
  System.out.print(b+" ");

 }
 System.out.println();

 System.out.println("字节数组换位字符串:"+str2);

 }

}

运行结果:

以上这篇详谈Java中的二进制及基本的位运算就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 利用Java读取二进制文件实例详解

    前言 本文主要给大家介绍了关于Java读取二进制文件的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 读Hex写CSV data目录下有little-endian bin文件,2个字节代表一个数字. bin存储的数据格式可自己定义.相同的方法可以直接应用到Android中. `-- networkProj |-- data |-- networkProj.iml |-- out `-- src 实现方法 private static void convertFiles

  • java 判断二进制文件的方法

    java 判断二进制文件的方法 直接上代码,实现方法很简单: 代码实现: public static boolean isBinary(File file) { boolean isBinary = false; try { FileInputStream fin = new FileInputStream(file); long len = file.length(); for (int j = 0; j < (int) len; j++) { int t = fin.read(); if (

  • JAVA中读取文件(二进制,字符)内容的几种方法总结

    JAVA中读取文件内容的方法有很多,比如按字节读取文件内容,按字符读取文件内容,按行读取文件内容,随机读取文件内容等方法,本文就以上方法的具体实现给出代码,需要的可以直接复制使用 public class ReadFromFile { /** * 以字节为单位读取文件,常用于读二进制文件,如图片.声音.影像等文件. */ public static void readFileByBytes(String fileName) { File file = new File(fileName); In

  • Java 中二进制转换成十六进制的两种实现方法

    Java 中二进制转换成十六进制的两种实现方法 每个字节转成16进制,方法1 /** * 每个字节转成16进制,方法1 * * @param result */ private static String toHex(byte[] result) { StringBuffer sb = new StringBuffer(result.length * 2); for (int i = 0; i < result.length; i++) { sb.append(Character.forDigi

  • java数据类型与二进制详细介绍

    java数据类型与二进制详细介绍 在java中 Int 类型的变量占 4个字节 Long 类型的变量占8个字节 一个程序就是一个世界,变量是这个程序的基本单位. Java基本数据类型 1.        整数类型 2.        小数(浮点数)类型 3.        布尔类型 4.        字符类型 整数类型 整数类型可以表示一个整数,常用的整数类型有:byte,short,int,long Byte  一个字节  -128到127 注:0有两个表示0000 0000正零  1000

  • java实现插入mysql二进制文件,blob类型,遇到问题及解决办法

    首先是数据库建立要准备的: 我们要把放置二进制字段设置为Blob类型,根据文件的大小选择合适的Blob类型,一下是各个Blob类型所能容纳二进制文件的大小 MySQL的四种BLOB类型 类型 大小(单位:字节) TinyBlob 最大 255 Blob 最大 65K MediumBlob 最大 16M LongBlob 最大 4G 一下是具体操作代码: 复制代码 代码如下: /** * * 把二进制文件(该二进制文件可以是本地硬盘路径,也可以是一个网络路径)存入数据库 * create date

  • Java字符串转成二进制码的方法

    Java将字符串转成二进制码,具体内容如下 public void toBinary(){ String str = "王雪"; char[] strChar=str.toCharArray(); String result=""; for(int i=0;i<strChar.length;i++){ result +=Integer.toBinaryString(strChar[i])+ " "; } System.out.println

  • Java实现较大二进制文件的读、写方法

    由于项目需要,需要对二进制文件进行读写.转换. 文件说明:由其他程序得到的二进制文件,文件内容为:包含23543个三角形.13270个顶点的三角网所对应的721组流速矢量(u.v)文件,通俗些说,一条数据包含两个双精度型的数值,每组数组包含23543条数据,如果以一个双精度数值为单位,则总共有23543 * 721 * 2 =33,949,006条数据.由Fortran程序以每 8 Byte存储一个数值的二进制文件存储,最终文件大小为下图所示: 测试:从该文件读出数据之后,转换为十进制,存储到另

  • 详谈Java中的二进制及基本的位运算

    二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.它的基数为2,进位规则是"逢二进一",借位规则是"借一当二",由18世纪德国数理哲学大师莱布尼兹发现.当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的.计算机中的二进制则是一个非常微小的开关,用"开"来表示1,"关"来表示0. 那么Java中的二进制又是怎么样的呢?让我们一起来揭开它神秘的面纱吧. 一.Java内置的进

  • 详谈Java中net.sf.json包关于JSON与对象互转的坑

    在Web开发过程中离不开数据的交互,这就需要规定交互数据的相关格式,以便数据在客户端与服务器之间进行传递.数据的格式通常有2种:1.xml:2.JSON.通常来说都是使用JSON来传递数据.本文正是介绍在Java中JSON与对象之间互相转换时遇到的几个问题以及相关的建议. 首先明确对于JSON有两个概念: JSON对象(JavaScript Object Notation,JavaScript对象表示法).这看似只存是位JavaScript所定制的,但它作为一种语法是独立于语言以及平台的.只是说

  • 详谈Java中instanceof和isInstance的区别

    一次性搞定instanceof和isInstance,instanceof和isInstance长的非常像,用法也很类似,先看看这两个的用法: obj.instanceof(class) 也就是说这个对象是不是这种类型, 1. 一个对象是本身类的一个对象 2. 一个对象是本身类父类(父类的父类)和接口(接口的接口)的一个对象 3. 所有对象都是Object 4. 凡是null有关的都是false  null.instanceof(class) class.inInstance(obj) 这个对象

  • 详谈Java中的事件监听机制

    鼠标事件监听机制的三个方面: 1.事件源对象: 事件源对象就是能够产生动作的对象.在Java语言中所有的容器组件和元素组件都是事件监听中的事件源对象.Java中根据事件的动作来区分不同的事件源对象,动作发生在哪个组件上,那么该组件就是事件源对象 2.事件监听方法: addMouseListener(MouseListener ml) ;该方法主要用来捕获鼠标的释放,按下,点击,进入和离开的动作:捕获到相应的动作后,交由事件处理类(实现MouseListener接口)进行处理. addAction

  • 详谈java中File类getPath()、getAbsolutePath()、getCanonical的区别

    简单看一下描述,例子最重要. 1.getPath(): 返回定义时的路径,(就是你写什么路径,他就返回什么路径) 2.getAbsolutePath(): 返回绝对路径,但不会处理"."和".."的情况 3.getCanonicalPath(): 返回的是规范化的绝对路径,相当于将getAbsolutePath()中的"."和".."解析成对应的正确的路径 第一个例子:(使用:".\\src\\test.txt&qu

  • 详谈Java中的Object、T(泛型)、?区别

    因为最近重新看了泛型,又看了些反射,导致我对Object.T(以下代指泛型).?产生了疑惑. 我们先来试着理解一下Object类,学习Java的应该都知道Object是所有类的父类,注意:那么这就意味着它的范围非常广!首先记住这点,如果你的参数类型时Object,那么的参数类型将非常广! <Thinking in Java>中说很多原因促成了泛型的出现,最引人注目的一个原因就是为了创造容器类.这个要怎么来理解呢?我的理解是,可以抛开这个为了创造容器类这个,而是回到泛型的目的是限定某种类型上来.

  • 详谈Java中Object类中的方法以及finalize函数作用

    Object是所有类的父类,任何类都默认继承Object. 一.Object类中的方法 1.clone方法 保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常. 主要是JAVA里除了8种基本类型传参数是值传递,其他的类对象传参数都是引用传递,我们有时候不希望在方法里讲参数改变,这是就需要在类中复写clone方法. 2.getClass方法 final方法,获得运行时类型. 3.toString方法 该方法

  • 详谈java中boolean和Boolean的区别

    boolean是基本数据类型 Boolean是它的封装类,和其他类一样,有属性有方法,可以new, 例如: Boolean flag = new Boolean("true"); // boolean 则不可以! Boolean 是boolean 的实例化对象类,和Integer对应int一样自jdk1.5.0以上版本后,Boolean在"赋值"和判断上和boolean一样, 即是你: boolean b1 = true ; 或者 Boolean b2 = true

  • 详谈Java中BigDecimal的一个除法异常

    如下所示: java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. 说明遇到除不尽的情况了,需要指定商的小数精度和舍入模式. 比如: a=b.divide(c,2,RoundingMode.HALF_UP); 以上这篇详谈Java中BigDecimal的一个除法异常就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • Java中两个大数之间的相关运算及BigInteger代码示例

    Java中两个大数之间的相关运算及BigInteger两段实例代码,具体如下. 大数相减 import java.util.Scanner; /* 进行大数相减,只能对两个正数进行相减 */ public class BigNumber { public static void main(String[] args) { Scanner scan=new Scanner(System.in); String a,b; while (scan.hasNext()) { BigNumber big=

随机推荐