我们都知道计算机中数据是以补码的形式存储的,那么怎么验证这个说法了?
比起传统的数值存储,汉字存储更有趣味,我们以汉字存储为例,以utf-8编码存储,一个汉字占用3个字节,而以gbk编码存储,一个汉字占用2个字节。为了便于运算,我们以“张”字为例,gbk解码得到数值,先通过在线网站查询到“张”字的gbk编码如下图:D5C5,转为二进制是:1101 0101 1100 0101 。(不会转换的,自己搜索16进制转二进制哈!)
用文末java代码验证一下,这个结果1101 0101 1100 0101是否正确,得到结果:(代码会在文末给出)
[-43, -59]
[11010101, 11000101]
二进制确实是正确。那到底是原码还是补码了?
如果是原码 11010101 = -(64+16+4+1)= -85, 11000101 = -(64+4+1)=-69,和上面的 -43,-59是冲突的。如果是补码,以第一个字节 11010101 为例,对应的反码是 11010100 ,原码是:10101011,等于-(32+8+2+1)=-43与上面的接口一致,看来计算机中真的是一个二进制补码的形式存储数据。下面给出代码:
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
public class ByteTest2 {
public static void main(String[] args) {
String s = "张";
System.out.println(getByteArray(s, "gbk"));
}
public static ArrayList<String> getByteArray(String content, String charsetName) {
byte[] bytes = new byte[0];
try {
bytes = content.getBytes(charsetName);
System.out.println(Arrays.toString(bytes));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
ArrayList<String> strings = new ArrayList<>();
for (int i = 0; i < bytes.length; i++) {
strings.add(byteToBinaryString(bytes[i]));
}
return strings;
}
/**
* byte转8位二进制字符串
*
* @param b
* @return
*/
public static String byteToBinaryString(byte b) {
/*
* & 字符与运算
* 例如: 0101 & 0110 = 0100
* 0xFF = 255 => 1111 1111
* 用byte和0xff相与,是因为int是32位,与0xff相与后就舍弃前面的24位,只保留后8位
* b & 0xFF 转换为int类型
*
* 0X100 = 256 => 0001 0000 0000
* bb + 0X100 补齐8位二进制
*/
int bb = b & 0xFF;
int bbb = bb + 0X100;
String result = Integer.toBinaryString(bbb).substring(1);
return result;
}
}