Java 如何把一个8位的时间类型字符串(“20150608”)存进一个定长为3的byte数组中?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 如何把一个8位的时间类型字符串(“20150608”)存进一个定长为3的byte数组中?相关的知识,希望对你有一定的参考价值。

public static void main(String[] args) 
int i;
//年月日初始化
int year = 2015;
int month = 1;
int day = 8;
//三个字节的数组
byte[] repo = new byte[3];
year = year << 12;
month = month << 6;
i = year | month | day;
//存日期
repo[2] = (byte)(i & 0xFF);
repo[1] = (byte)((i >> 8) & 0xFF);
repo[0] = (byte)(i >> 16);

//取日期
day = repo[2] & 0x3F;
month = (((repo[1] << 2) & 0x3F) | ((repo[2] >> 6) & 0x3)) & 0x3F;
year = (repo[0] << 4) | ((repo[1] >> 4) & 0xF);
System.out.println(day);
System.out.println(month);
System.out.println(year);

参考技术A 怎样的组合呢,两个数字一组、还是别的方法

~
~
~
参考技术B 操,这是公司的面试题啊!

Question20180128 补位的两种方式

  我们都知道Java的基本数据类型都有一个固定的位数,如byte占8位,int占32位等。正因如此,当把一个低精度的数据类型转成一个高精度的数据类型时,必然会涉及到如何扩展位数的问题。这里有两种解决方案:
(1)补零扩展:填充一定位数的0。
(2)补符号位扩展:填充一定位数的符号位(非负数填充0,负数填充1)。
  对于无符号类型(相当于都是非负数)与有符号类型中的非负数部分,这两种方法没有区别,都是填充0;对于有符号类型中的负数部分,这两种方法就会产生差异了,补零扩展会填充0,而补符号位扩展会填充1。下面将byte类型的-127转为int类型为例,探讨一下这两种方法的区别。
  首先必须明确一些知识点:

  • 计算机是用补码来存储数字的;
  • 正数的补码等于原码;
  • 负数的补码等于反码+1;
  • 一个数的补码的补码等于原码。

  127原码1111 1111,反码1000 0000,补码1000 0001。计算机存储的是1000 0001,用十六进制表示为0x81。


  当使用补零扩展时,结果为: 0000 0000 0000 0000 0000 0000 1000 0001
  用十六进制表示为0x81。为了计算十进制值,计算它的补码,结果为: 0000 0000 0000 0000 0000 0000 1000 0001
  将这个二进制数转成十进制的结果是129。


  当使用补符号位扩展时,结果为: 1111 1111 1111 1111 1111 1111 1000 0001
  用十六进制表示为0xFFFFFF81。为了计算十进制值,计算它的补码,结果为: 1000 0000 0000 0000 0000 0000 0111 1111
  将这个二进制数转成十进制的结果是-127。
由此可以得出结论:
(1)使用补零扩展能够保证二进制存储的一致性,但不能保证十进制值不变。
(2)使用补符号位扩展能够保证十进制值不变,但不能保证二进制存储的一致性。
下面以Java为例进行验证(Java中没有无符号类型,只有有符号类型):

public static void main(String[] args){
    byte b = -127;
    System.out.println(Integer.toBinaryString((int)b));
    System.out.println(Integer.toBinaryString((int)(b & 0xFF)));
}
& 是按位与运算符 ,0xff二进制就是1111 1111。& 运算是,如果对应的两个bit都是1,则那个bit结果为1,否则为0.
比如 1010 & 1101 = 1000 (二进制)
由于0xff最低的8位是1,因此number中低8位中的&之后,如果原来是1,结果还是1,原来是0,结果位还是0.高于8位的,0xff都是0,所以无论是0还是1,结果都是0。
输出:
11111111111111111111111110000001
10000001

由此又可以得出结论:
(1)对于有符号类型,Java使用的是补符号位扩展,这样能保证十进制的值不变;
(2)如果想要用补零扩展来确保二进制的内容不变,可以通过& 0xFF(不一定是8位,根据待转换的数据位数而定)实现。本质是将前面补上的1都通过与运算改成了0。
关于b & 0xFF为什么会导致结果改变的问题,是因为byte在进行这个运算之前先转换为了默认类型int,后面的0xFF也进行了相应的位扩展,通过补充符号位,计算如下:

11111111111111111111111110000001
       &
00000000000000000000000011111111
       ||
00000000000000000000000010000001

  这里就是补码的两种方式,了解了这个有助于我们了解精度的问题;

注:文章参考http://blog.csdn.net/swt369/article/details/77931936

以上是关于Java 如何把一个8位的时间类型字符串(“20150608”)存进一个定长为3的byte数组中?的主要内容,如果未能解决你的问题,请参考以下文章

如何写java产生一个随机8位的数

Java的8种基本数据类型及它们的包装类型占用内存分析

Question20180128 补位的两种方式

如何把一段字符串转对应的32位的整数来唯一标识,就如Hash一样

Java字符的数据类型

为啥我不能把 0xffff 放到 java 中的短