decimal,binary,hex,Two’s Complement Notation
二进制转十进制
很简单,从右往左加,第一位乘以2的零次方,第二位乘以2的一次方,然后以此类推…… 还有一种方法是Horner’s Rule,从左往右算,每次把下一位加在这个结果中作为一个整体。
十进制转二进制
不断地除以二,直到除不动了为止,每一步得到的余数倒过来就是所求的二进制。 - 10/2=5 ...0 - 5/2=2 ... 1 - 2/2=1 ... 0 - 1/2=0 ... 1
所以10的二进制为1010 当然,如果不想最后再颠倒一遍的话,可以算的时候从下往上写XD
十六进制转二进制
十六进制的每一位都能转换成一个四位的二进制,然后把它们拼起来就好,其实还有一个转换表,但算起来也不麻烦,我觉得不背也行。
二进制转十六进制
和上面一个道理,每四位二进制都能转换成一位十六进制,如果最后一组不足四位填上几个零就好。
十六进制转十进制
和二进制转十进制一个道理,只不过把2换成16了而已。
十进制转十六进制
同上,和二进制一样,只不过不断除以16。
Two’s Complement
这是一种用二进制表达整数(包括正负)的一种方法。 首先,从最左边的那一位可以看出这个数字的正负——0为正,1为负。 如果是正数的话,和之前讲到的传统二进制表达是相同的。 如果是负数的话,想要知道它的具体值,我们需要将Two’s Complement转换成它的相反数(也就是说这个数字的整数版本)。 转换成相反数的算法如下(同时适用与正数和负数): - 将每一位的数字颠倒(颠倒指的是,1换成0,0换成1) - 在颠倒之后的基础上再+1
比如这里有个我瞎编的32bits的数字: 1010 0100 0100 1111 1010 1100 0101 0000 第一位是1,所以这个数是小于零的 首先我们要把它变成这样的: 0101 1011 1011 0000 0101 0011 1010 1111 然后再+1就变成了这样: 0101 1011 1011 0000 0101 0011 1011 0000 这个数就是最前面瞎编的那个数的相反数
哦对了,因为32bits的二进制写起来太长了,所以经常会用十六进制来表示。
Big & Little Endian
Endianness 指的是电脑储存多字节数值的顺序。
Least Significant Byte (LSB) 指的是一个数值中最小的那个字节(不是比特),而 Most Significant Byte (MSB) 指的是一个数值中最大的那个字节。Endianness的大小由他们的储存顺序决定,如果最低的地址中储存的是 MSB,那么就是 Big Endian,而如果最低的地址中储存的是 LSB,那么就是 Little Endian。
一般来讲,除了JAVA虚拟机恒定用 Big Endian 之外,大小端的读取和存储都是由机器的系统决定的,所以如果机器系统使用的 Endianness 不同,在储存和读取时会出现错误。
如何确定系统是 Big Endian 还是 Little Endian?
第一个想到的是使用位运算符。但位运算符会默认比特已经按照最大的比特到最小的比特排列,所以无法反映系统真实的字节排列顺序。
我们可以利用C语言的特性:char
是一个字节的数据型,因此我们可以将一个整数转换成一个指向char
第一个字节(即最低内存地址)的指针,然后查看这个指针指向的数值。以32(也有可能是8)位整数1为例,它的 MSB是0,LSB是1,最大的字节是00(0),最小的字节是01(1)。如果第一个char
为0就是 Big Endian,为1就是 Little Endian。
bool isLittleEndian() {
int testNum;
char *ptr;
testNum = 1;
ptr = (char *) &testNum;
return (*ptr);
}