java字符串操作与位运算
各种进制之间的转换详解!!!
1、数制及数制的转换
一、数制
数制是人们利用符号进行计数的科学方法。数制有很多种,在计算机中常用的数制有:十进制,二进制和十六进制。
数制也称计数制,是指用一组固定的符号和统一的规则来表示数值的方法。计算机是信息处理的工具,任何信息必须转换成二进制形式数据后才能由计算机进行处理,存储和传输。
编辑本段
1)十进制数(Decimal)
人们通常使用的是十进制。它的特点有两个:有0,1,2….9十个基本数字组成,十进制数运算是按“逢十进一”的规则进行的.
在计算机中,除了十进制数外,经常使用的数制还有二进制数和十六进制数.在运算中它们分别遵循的是逢二进一和逢十六进一的法则.
编辑本段
2)二进制数(Binary)
二进制数有两个特点:它由两个基本数字0,1组成,二进制数运算规律是逢二进一。
为区别于其它进制数,二进制数的书写通常在数的右下方注上基数2,或加后面加B表示。
例如:二进制数10110011可以写成(10110011)2,或写成10110011B,对于十进制数可以不加注.计算机中的数据均采用二进制数表示,这是因为二进制数具有以下特点:
(1) 二进制数中只有两个字符0和1,表示具有两个不同稳定状态的元器件。例如,电路中有,无电流,有电流用1表示,无电流用0表示。类似的还比如电路中电压的高,低,晶体管的导通和截止等。
(2) 二进制数运算简单,大大简化了计算中运算部件的结构。
二进制数的加法和乘法运算如下:
0+0=0 0+1=1+0=1 1+1=10
0×0=0 0×1=1×0=0 1×1=1
3)八进制数(Octal)
由于二进制数据的基R较小,所以二进制数据的书写和阅读不方便,为此,在小型机中引入了八进制。八进制的基R=8=2^3,有数码0、1、2、3、4、5、6、7,并且每个数码正好对应三位二进制数,所以八进制能很好地反映二进制。八进制用下标8或数据后面
加Q表示 例如:二进制数据
( 11 101 010 . 010 110 100 )2 对应
八进制数据 ( 3 5 2 . 2 6 4 )8或352.264Q.
4)十六进制数(Hex)
由于二进制数在使用中位数太长,不容易记忆,所以又提出了十六进制数
十六进制数有两个基本特点:它由十六个字符0~9以及A,B,C,D,E,F组成(它们分别表示十进制数10~15),十六进制数运算规律是逢十六进一,即基R=16=2^4,通常在表示时用尾部标志H或下标16以示区别。
例如:十六进制数4AC8可写成(4AC8)16,或写成4AC8H。
一、数制转换
1) 十---->二
比如:6,如果将它转换成二进制数呢?
10进制数转换成二进制数,这是一个连续除2的过程:
把要转换的数,除以2,得到商和余数,
将商继续除以2,直到商为0。最后将所有余数倒序排列,得到数就是转换结果。
听起来有些糊涂?我们结合例子来说明。比如要转换6为二进制数。
“把要转换的数,除以2,得到商和余数”。
那么:
十转二示意图
要转换的数是6, 6
÷ 2,得到商是3,余数是0。
“将商继续除以2,直到商为0……”
现在商是3,还不是0,所以继续除以2。
那就: 3 ÷ 2, 得到商是1,余数是1。
“将商继续除以2,直到商为0……”
现在商是1,还不是0,所以继续除以2。
那就: 1 ÷ 2, 得到商是0,余数是1
“将商继续除以2,直到商为0……最后将所有余数倒序排列”
好极!现在商已经是0。
我们三次计算依次得到余数分别是:0、1、1,将所有余数倒序排列,那就是:110了!
6转换成二进制,结果是110。
把上面的一段改成用表格来表示,则为:
被除数 计算过程 商 余数
6 6/2 3 0
3 3/2 1 1
1 1/2 0 1
(在计算机中,÷用 / 来表示)
2) 二 ----> 十
二进制数转换为十进制数
二进制数第0位的权值是2的0次方,第1位的权值是2的1次方……
所以,设有一个二进制数:0110 0100,转换为10进制为:
下面是竖式:
0110 0100 换算成 十进制
备注:" ^ " 为次方
第0位 0 *
2^0 = 0
第1位 0 *
2^1 = 0
第2位 1 *
2^2 = 4
第3位 0 *
2^3 = 0
第4位 0 *
2^4 = 0
第5位 1 *
2^5 = 32
第6位 1 *
2^6 = 64
第7位 0 *
2^7 = 0 +
---------------------------
100
0乘以多少都是0,所以我们也可以直接跳过值为0的位
3. 十 ----> 八
10进制数转换成8进制的方法,和转换为2进制的方法类似,唯一变化:除数由2变成8。
来看一个例子,如何将十进制数120转换成八进制数。
用表格表示:
被除数 计算过程 商 余数
120 120/8 15 0
15 15/8 1 7
1 1/8 0 1
120转换为8进制,结果为:170。
4)八 ----> 十
八进制就是逢8进1。
八进制数采用 0~7这八数来表达一个数。
八进制数第0位的权值为8的0次方,第1位权值为8的1次方,第2位权值为8的2次方……
所以,设有一个八进制数:1507,转换为十进制为:
用竖式表示:
1507换算成十进制。
第0位 7 *
8^0 = 7
第1位 0 *
8^1 = 0
第2位 5 *
8^2 = 320
第3位 1 *
8^3 = 512
--------------------------
839
同样,我们也可以用横式直接计算:
7 * 8^0 + 0 * 8^1 + 5 * 8^2 + 1
- 8^3 = 839
结果是,八进制数 1507 转换成十进制数为 839
5) 十 ----> 十六
10进制数转换成16进制的方法,和转换为2进制的方法类似,唯一变化:除数由2变成16。
同样是120,转换成16进制则为:
被除数 计算过程 商 余数
120 120/16 7 8
7 7/16 0 7
120转换为16进制,结果为:78。
6) 十六----> 十
16进制就是逢16进1,但我们只有0~9这十个数字,所以我们用A,B,C,D,E,F这五个字母来分别表示10,11,12,13,14,15。字母不区分大小写。
十六进制数的第0位的权值为16的0次方,第1位的权值为16的1次方,第2位的权值为16的2次方……
所以,在第N(N从0开始)位上,如果是是数 X (X 大于等于0,并且X小于等于 15,即:F)表示的大小为 X * 16的N次方。
假设有一个十六进数 2AF5, 那么如何换算成10进制呢?
用竖式计算:
2AF5换算成10进制:
第0位: 5 *
16^0 = 5
第1位: F *
16^1 = 240
第2位: A *
16^2 = 2560
第3位: 2 *
16^3 = 8192 +
-------------------------------------
10997
(别忘了,在上面的计算中,A表示10,而F表示15)
现在可以看出,所有进制换算成10进制,关键在于各自的权值不同。
假设有人问你,十进数 1234 为什么是 一千二百三十四?你尽可以给他这么一个算式:
1234 = 1 * 10^3 + 2 * 10^2 + 3 *
10^1 + 4 * 10^0
7) 二 ----> 八
(11001.101)(二)
整数部分: 从后往前每三位一组,缺位处用0填补,然后按十进制方法进行转化,
则有:
001=1
011=3
然后我们将结果按从下往上的顺序书写就是:31,那么这个31就是二进制11001的八进制形式
小数部分: 从前往后每三位一组,缺位处用0填补,然后按十进制方法进行转化,
则有:
101=5
然后我们将结果部分按从上往下的顺序书写就是:5,那么这个5就是二进制0.101的八进制形式
所以:(11001.101)(二)=(31.5)(八)
8) 八 ----> 二
(31.5)(八)
整数部分:从后往前每一位按十进制转化方式转化为三位二进制数,缺位处用0补充 则有:
1---->1---->001
3---->11
然后我们将结果按从下往上的顺序书写就是:11001,那么这个11001就是八进制31的二进制形式
说明,关于十进制的转化方式我这里就不再说了,上一篇文章我已经讲解了!
小数部分:从前往后每一位按十进制转化方式转化为三位二进制数,缺位处用0补充 则有:
5---->101
然后我们将结果按从下往上的顺序书写就是:101,那么这个101就是八进制5的二进制形式
所以:(31.5)(八)=(11001.101)(二)
9) 十六 ----> 二 ;二 ----> 十六
二进制和十六进制的互相转换比较重要。不过这二者的转换却不用计算,每个C,C++程序员都能做到看见二进制数,直接就能转换为十六进制数,反之亦然。
我们也一样,只要学完这一小节,就能做到。
首先我们来看一个二进制数:1111,它是多少呢?
你可能还要这样计算:1 * 2^0 + 1 * 2^1 + 1
* 2^2 + 1 * 2^3 = 1 * 1 + 1 * 2 + 1 * 4 + 1 * 8 = 15。
然而,由于1111才4位,所以我们必须直接记住它每一位的权值,并且是从高位往低位记,:8、4、2、1。即,最高位的权值为2^3 = 8,然后依次是 2^2 = 4,2^1=2, 2^0 = 1。
记住8421,对于任意一个4位的二进制数,我们都可以很快算出它对应的10进制值。
下面列出四位二进制数 xxxx 所有可能的值(中间略过部分)
仅4位的2进制数
快速计算方法 十进制值 十六进值
1111 = 8 + 4 + 2 + 1 = 15 F
1110 = 8 + 4 + 2 + 0 = 14 E
1101 = 8 + 4 + 0 + 1 = 13 D
1100 = 8 + 4 + 0 + 0 = 12 C
1011 = 8 + 0 + 2+ 1 = 11 B
1010 = 8 + 0 + 2 + 0 = 10 A
1001 = 8 + 0 + 0 + 1 = 9 9
....
0001 = 0 + 0 + 0 + 1 = 1 1
0000 = 0 + 0 + 0 + 0 = 0 0
二进制数要转换为十六进制,就是以4位一段,分别转换为十六进制。
如(上行为二制数,下面为对应的十六进制):
1111 1101 , 1010 0101 , 1001 1011
F D , A 5 , 9 B
反过来,当我们看到 FD时,如何迅速将它转换为二进制数呢?
先转换F:
看到F,我们需知道它是15(可能你还不熟悉A~F这五个数),然后15如何用8421凑呢?应该是8 + 4
- 2 + 1,所以四位全为1 :1111。
接着转换 D:
看到D,知道它是13,13如何用8421凑呢?应该是:8 +
4 + 1,即:1101。
所以,FD转换为二进制数,为: 1111 1011
由于十六进制转换成二进制相当直接,所以,我们需要将一个十进制数转换成2进制数时,也可以先转换成16进制,然后再转换成2进制。
比如,十进制数 1234转换成二制数,如果要一直除以2,直接得到2进制数,需要计算较多次数。所以我们可以先除以16,得到16进制数:
被除数 计算过程 商 余数
1234 1234/16 77 2
77 77/16 4 13 (D)
4 4/16 0 4
结果16进制为:
0x4D2
然后我们可直接写出0x4D2的二进制形式: 0100 1101 0010。
其中对映关系为:
0100 – 4
1101 – D
0010 – 2
同样,如果一个二进制数很长,我们需要将它转换成10进制数时,除了前面学过的方法是,我们还可以先将这个二进制转换成16进制,然后再转换为10进制。
下面举例一个int类型的二进制数:
01101101 11100101 10101111
00011011
我们按四位一组转换为16进制: 6D E5 AF 1B
2、补码
所有的整数类型(除了char 类型之外)都是有符号的整数。这意味着他们既能表示正数,又能表示负数。 Java使用补码来表示二进制数 ,在补码表示中 ,最高位为符号位 ,正数的符号位为0,负数为1。补码的规定如下 :
对正数来说 ,最高位为0,其余各位代表数值本身(以二进制表示),如 +42的补码 为
00101010。
对负数而言 ,把该数绝对值的补码按位取反 ,然后对整个数加 1,即得该数的补码 。 如-42的补码为11010110(00101010按位取反11010101 +1=11010110 )
用补码来表示数 ,0的补码是唯一的 ,都为00000000。 (而在原码 ,反码表示中,+0和-0的表
示是不唯一的,可参见相应的书籍 )。而且可以用 111111表示-1的补码(这也是补码与原码
和反码的区别)。
先把负数写为其补码形式(在此不议),然后再根据二进制转换其它进制的方法进行。
如-12的补码
第一步:转换成二进制
1000 0000 0000 1100
第二步:补码,取反加一
注意:取反时符号位不变!
1111 1111 1111 0100
3、位运算符位运算符用来对二进制位进行操作 ,Java中提供了如下所示的位运算符 :
位运算符(>>,<<,>>>,&,|,^,~) ,位运算符中 ,除~ 以外,其余均为二元运算符 。 操作数只能为整型和字符型数据 。
Java 位运算符
Java 定义的位运算(bitwise operators )直接对整数类型的位进行操作,这些整数类型包括long,int,hort,char,and
byte 。表4-2 列出了位运算:
-
运算符 结果
-
按位非(NOT)(一元运算)
& 按位与(AND)
| 按位或(OR)
^ 按位异或(XOR)
>>
右移
>>>
右移,左边空出的位以0填充 ;无符号右移
<<
左移
&=
按位与赋值
|= 按位或赋值
^= 按位异或赋值
>>=
右移赋值
>>>=
右移赋值,左边空出的位以0填充 ;无符号左移
<<=
左移赋值
按位
非(NOT)
按位非也叫做补,一元运算符NOT“~”是对其运算数的每一位取反。例如,数字42,它的二进制代码为: 00101010
经过按位非运算成为 11010101
按位与(AND)
按位与运算符“&”,如果两个运算数都是1,则结果为1。其他情况下,结果均为零。看下面的例子: 00101010 42 &00001111 15
00001010 10
按位或(OR)
按位或运算符“|”,任何一个运算数为1,则结果为1。如下面的例子所示:
00101010 42 | 00001111 15
00101111 47
按位异或(XOR)
按 位异或运算符“^”,只有在两个比较的位不同时其结果是 1。否则,结果是零。下面的例子显示了“^”运算符的效果。这个例子也表明了XOR 运算符的一个有用的属性。注
4、数组(重点)
数组是有序数据的集合,数组中的每个元素具有相同的数组名,根据数组名和下标来唯一确定数组中的元素。使用时要先声明后创建
一、一位数组
1) 一维数组的声明
格式:
数据类型 数组名[
] 或 数据类型 [ ]数组名
例: int a[] ; String s[] ; char
[]c ;
说明:定义数组,并不为数据元素分配内存,因此“[ ]”中不用指出数组中元素个数。
2
)一维数组的创建与赋值
创建数组并不是定义数组,而是在数组定义后,为数组分配存储空间,同时对数组元素进行初始化
(1)用运算符new 分配内存再赋值
格式:
数组名=new 数据类型[size]
例:int a[] ;
a=new int[3] ; // 产生a[0] , a[1] , a[2] 三个元素
a[0]=8 ; a[1]=8 ; a[2]=8 ;
3)直接赋初值并定义数组的大小
例:int i[]={4,5,010,7,3,2,9} ;
String names[]={“张三”,”李四”,”王五”,”宋七”} ;
4)测试数组长度(补充)
格式:
数组名.length
char c[]={‘a’,’b’,’c’,’北’,’京’} ;
System.out.print(c.length) ;
// 输出5
二、多维数组
以二维数组为例
例:int d[][] ; // 定义一个二维数组
d=new int[3][4] ; // 分配3 行4 列数组内存
int a[][]=new int[2][] ;
a[
0]=new int[3] ; // 第二维第一个元素指向3 个整型数
a[1]=new int[5] ; // 第二维第一个元素指向5 个整型数
注意:Java 可以第二维不等长
int
i[][]={{0},{1,4,5},{75,6},{8,50,4,7}} ; //定义和赋初值在一起
下面数组定义正吴的判断
int a[][]=new int[10,10] //错
int a[1
0][10]=new int[][] //错
int a[][]=new int[10][10] //错
int []a[]=new int[10][10] //对
int [][]a=new int[10][10] //对
注意:java中二维数组分配空间是第二维可以为空,但是第一维必须分配内存。
5、字符串
字符串的几种用法:
拼接 直接用“+”把两个字符串拼接起来
例如:String firstName = “li”;
String
secondName = “ming”;
String
fullName = firstName+secondName;
检测字符串是否相等 检测两个字符串内容是否相等时使用“equals
”;比较两个字符串的引用是否相等时用“==
”
得到字符串的长度 字符串变量名.length();