前言
在2019年的时候,公司就开始提倡让Domino技术线的同事对Java相关的技术进行学习。其实,由于各种项目上的杂事,我并未按公司的要求投入精力去研究与工作任务不相关的技术。
这并不能说明我抵触公司的技术学习建议,也不是我不喜欢学习新东西。也就是在这2020年初疫情严重,居家隔离的日子里,我开始了Java基础技能的学习(也可以叫做“唤醒”吧,十年之前也接触过很长一段的Java开发)。
为了简单,我从w3school在线站点中找到了Java相关的信息,学了起来,在 《Java 基本数据类型》中,读到
byte:
byte数据类型是8位、有符号的,以二进制补码表示的整数;
最小值是-128(-2^7);
最大值是127(2^7-1);
默认值是0;
byte类型用在大型数组中节约空间,主要代替整数,因为byte变量占用的空间只有int类型的四分之一;
例子:byte a = 100,byte b = -50。
时,发现了一些东西似懂非懂的,我也不想囫囵吞枣地草草学习。如
为什么short类型的变量可以表示的最小值是-128,不是说首位是符号位吗?(我想着最小位还是(11111111)2)呢!!
注:其实,long、int、short、byte在表示数值范围方面的规律都是相通的,本文中我就以byte类型为例阐述。
byte类型基础知识
时,也就相当于在内存中申请了长度为8的内存块——每一位只能放0或1,这样一来就有2^8种组合状态
(0000 0000)2
(0000 0001)2
… …
(1111 1101)2
(1111 1110)2
(1111 1111)2
如果将这些二进制数转为十进制,那么它的范围将是[0,255]。可惜的是,在byte类型中,也要对负数进行表示。而在Java语言中,byte类型做为带符号数,将8位中的第一位用作符号(+或-)位,剩余的7位表示数值。
正值的表示
8位二进制的第一位为0时,表示正数,用原码表示正数。像下面这样:
(0000 0001)2
(0111 0000)2
…
都是正数,分别表示了十进制中的1和112。这样,对于序列(0111 1111)2(2^7-1)就是byte类型能表示的最大值了。
特别一点:(0000 0000)2 就是十进制的0
负值的表示
8位二进制的第一位为1时,表示负数,用补码表示负数。像下面这样:
(1000 0001)2
(1111 1110)2
(1111 1111)2
…
都是负数,分别表示了十进制中的-127、-2和-1。是怎么计算出来的呢?拿(1111 1110)2为例分析:
- 二进制的第一位,表示这个数字是负的;
- 再减1,得到(1111 1101)2;
- 再按位取反,得到(0000 0010)2(注意,此时第1位已不再表示符号,所以这个值是2),这个2你可以理解为原始十进制负数的绝对值。
- 将第一步与第三步得到的信息合并一下,可以知道(1111 1110)2表示的值是-2
这时候说说,byte能表示的最小值吧。我们看看(1000 0000)2这个二进制数。与下面的分析过程一一对应,我们来一遍。
- 二进制的第一位,表示这个数字是负的;
- 再减1,得到(0111 1111)2;
- 再按位取反,得到(1000 0000)2(注意,此时第1位已不再表示符号,所以这个值是2^7,即128)
- 将第一步与第三步得到的信息合并一下,可以知道(1000 0000)2表示的值是-128
最后
闲着无聊,写一段代码。输出一个整数的二进制序列吧!
代码:
package com.tianyq;
public class ClsOutputBinaryStr {
public static void main(String[] args) {
// TODO Auto-generated method stub
//printBinaryStr(new Byte((byte) -117));
System.out.println("byte类型的数值-117在计算机中的二进制表示为:" + printBinaryStr(new Byte((byte) -117)));
// printBinaryStr(new Short((short)3));
System.out.println("short类型的数值-20000在计算机中的二进制表示为:" + printBinaryStr(new Short((short)-20000)));
// printBinaryStr(new Integer(3));
System.out.println("int类型的数值12580在计算机中的二进制表示为:" + printBinaryStr(new Integer(12580)));
// printBinaryStr(new Long(3));
System.out.println("long类型的数值823742430859l在计算机中的二进制表示为:" + printBinaryStr(new Long(823742430859l)));
}
// 泛型方法 printArray
public static <E> String printBinaryStr(E input) {
String result = "";
int byteLen = -1;
long from = 0;
switch (input.getClass().toString()) {
case "class java.lang.Byte": // 一个字节 8 位
System.out.println("Byte");
Byte b = (Byte) input;
from = b.byteValue();
byteLen = 8;
break;
case "class java.lang.Short": // 二个字节 16 位
System.out.println("Short");
Short s = (Short) input;
from = s.shortValue();
byteLen = 16;
break;
case "class java.lang.Integer": // 四个字节 32位
System.out.println("Integer");
Integer i = (Integer) input;
from = i.intValue();
byteLen = 32;
break;
case "class java.lang.Long": // 八个字节 64位
System.out.println("Long");
Long l = (Long) input;
from = l.longValue();
byteLen = 64;
break;
default:
System.out.println(input.getClass().toString());
break;
}
if (byteLen == -1) {
return result;
}
long formCp = Math.abs(from);
StringBuffer sb = new StringBuffer();
//以下代码会计算出from绝对值的原码
do {
sb.append(formCp % 2);
formCp = formCp >> 1;
} while (formCp != 0);
//补0
for(int index = sb.length(); index < byteLen - 1; index ++){
sb.append("0");
}
//如果是正数
if(from >= 0){
sb.append("0");
}else{
sb.append("1");
}
//以下是原码
//原码:一个正数,按照绝对值大小转换成的二进制数;一个负数按照绝对值大小转换成的二进制数,然后最高位补1,称为原码。
sb = sb.reverse();
//System.out.println(from + " 的绝对值的二进制原码 " + sb.toString());
result = sb.toString();
//负数复杂一点,因为 在计算机中,负数以原码的补码形式表达
if(from < 0){
//得到反码 - 反码:正数的反码与原码相同,负数的反码为对该数的原码除符号位外各位取反
//每一位取反(除符号位)
for(int index = 1; index < byteLen; index ++){
if(sb.charAt(index) == '1'){
sb.setCharAt(index, '0');
}else{
sb.setCharAt(index, '1');
}
}
//System.out.println(from + " 的二进制反码 " + sb.toString());
//补码:正数的补码与原码相同,负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1
//通过从尾部查找字符,模拟二进制加法
for(int index = byteLen - 1; index > 0; index --){
if(sb.charAt(index) == '0'){
sb.setCharAt(index, '1');
break;
}else{
sb.setCharAt(index, '0');
}
}
//System.out.println(from + " 的二进制补码 " + sb.toString());
result = sb.toString();
}
return result;
}
}
以上代码的执行结果如下:
Byte
byte类型的数值-117在计算机中的二进制表示为:10001011
Short
short类型的数值-20000在计算机中的二进制表示为:1011000111100000
Integer
int类型的数值12580在计算机中的二进制表示为:00000000000000000011000100100100
Long
long类型的数值823742430859l在计算机中的二进制表示为:0000000000000000000000001011111111001010110111111111111010001011
OK,文章写到这里就结束了。