- 2.1 整数的二进制表示与位运算
- 2.2 小数的二进制表示
- 2.3 字符的编码与乱码
- 2.3.2 Unicode编码
- 2.3.3 编码转换
- 2.3.4 乱码的原因
- 2.3.5 从乱码中恢复
- 2.4 char的真正含义
2.1 整数的二进制表示与位运算
2.1.1 正整数的二进制表示
2.1.2 负整数的二进制表示
- 负数的二进制表示就是对应的正数的补码。
- 补码:原码取反加1
- 原因:计算机只能做加法
2.1.3 十六进制
- 0x
- Java7之前不支持直接写二进制常量,一般补足8位,用16进制表示
- Java7开始支持二进制常量 0b或0B
2.1.4 位运算
- 移位运算
- 左移:« 向左移动,右边低位补0
- 无符号右移:»> 向右移动,左边高位补0
- 有符号右移:» 向右移动,左边补0或者补1取决于以前的最高位。
- 逻辑运算
- 按位与
- 按位或
- 按位取反
- 按位异或
2.2 小数的二进制表示
2.2.1 小数的计算为何会出错
不是运算本身会出错,而是计算机无法精确的表示很多数。
- 转化为整数进行运算,运算完成后再转换为小数
- 或者使用十进制的数据类型(BigDecimal)
2.2.2 二进制的表示
- float:32位
- double:64位
2.3 字符的编码与乱码
2.3.1 常见的非Unicode编码
- ASCII
- American Standard Code for Information Interhange 美国信息互换标准代码
- 单字节,8位,最高位为0,表示127种字符
- ISO 8859-1
- 西欧
- 单字节,8位
- 0-127与ASCII码一致
- Windows-1252
- 与ISO 8859-1基本一致
- 实际在应用中已经取代ISO 8859-1
- GB2312
- 固定双字节,16位
- 在两个字节中,最高位都是1。如果是0,就认为是ASCII字符。
- GBK
- 向下兼容GB2312
- 固定双字节,低字节的最高位可能为0。
- 在解析二进制流的过程中,如果第一个字节的最高位为1,那么就将下一个字节读进来一起解析为一个汉字。而不用考虑它的最高位。解析完成后,跳到第三个字节继续解析。
- GB18030
- 向下兼容GBK
- 变长编码,双字节或者4字节。
- Big5
- 固定双字节
- 繁体
2.3.2 Unicode编码
- 给世界上所有的字符都分配了一个唯一的数字编号
- 并未规定这个编号对应到二进制表示
- UTF-32
- 字符编号的整数二进制形式
- 4字节
- 高位存放在前BE,否则LE
- UTF-16
- 变长,2字节或4字节
- UTF-8
- 使用字节数1-4不等
2.3.3 编码转换
编码转换改变了字符的二进制内容,但并没有改变字符看上去的样子。
2.3.4 乱码的原因
- 解析错误
- 错误的解析和编码转换
2.3.5 从乱码中恢复
- 使用UltraEdit
-
使用Java
public static void recover(String str) throws UnsupportedEncodingException { String[] charsets = new String[]{"windows-1252", "GB18030", "Big5", "UTF-8"}; for(int i = 0; i < charsets.length; i++) { for(int j = 0; j < charsets.length; j++) { if(i!=j) { String s = new String(str.getBytes(charsets[i]), charsets[j]); System.out.println("--- 原来编码(A)假设是:"+charsets[j]+", 被错误解读为了(B):"+charsets[i]); System.out.println(s); System.out.println(); } } } }
- getBytes 可以获取一个字符串的给定编码格式的二进制形式
- String(byte bytes[], String charsetName)的构造方法可以给定的二进制数组bytes按照编码格式charsetName解读为一个字符串。
2.4 char的真正含义
- char本质上是一个固定占用两个字节的无符号正整数,这个整数对应于Unicode编号,这个正整数对应于Unicode编号对应的字符
- 由于固定占用两个字节,char只能表示Unicode编号在65536以内的字符
- 超过的部分使用两个char。
char的多种赋值方式:
char c = '马';
char c = 39532;
char c = 0x9a6c;
char c = '\u9a6c'