Yulong Niu

个人博客

探索Java基本类型的二进制表示

Posted at — May 16, 2017

1. 基本数据类型

Java有八种基本数据类型(primitive data type),分别是booleancharbyteshortintlongfloatdouble,所占用的比特数如下表所示。

Data typeBitRange
booleannot precisely definedTrue or false
charunsigned 16$2^{16}$
bytesigned 8$-2^{7}$ ~ $2^7-1$
shortsigned 16$-2^{15}$ ~ $2^{15}-1$
intsigned 32$-2^{31}$ ~ $2^{31}-1$
longsigned 64$-2^{63}$ ~ $2^{63}-1$
floatsigned 32$\pm (1-2^{-24}) * 2^{128}$ 精度$2^{-126}$

2. 整数二进制表示和范围

byte类型为例,每个整数占用了8个比特,最左边比特位表示正负(0为正,1为负)。例如,$1$表示为$0000 0001_2$。因此,能表示的最大正整数为$0111 1111_2$,即

$$ 2^0 + 2^1 + 2^2 + \cdots + 2^6 = 2^7 - 1 $$

由于要满足$-1 + 1 = 0$,所以$-1$表示为$1111 1111_2$,$-2$表示为$1111 1110_2$。类似于正整数,可以得到能表示的最大负整数为$1000 0001_2$,即$-(2^7 - 1)$。

但是,这里出现一个问题:出现了两个0,一个是$+0$($0000 0000_2$),一个是$-0$($1000 0000_2$)。因此,规定$1000 0000_2$为最大负整数$-2^7$。

3. 浮点数二进制表示和范围

Java使用IEEE 754标准表示浮点数,其二进制表示分为三个部分:1. 最左边比特位表示正负(0为正,1为负);2. 指数(float有8个比特位,double有11比特位);3. 尾数(float有23个比特位,double有52比特位)。同时,由于指数需要区分正负,所以float指数位转为十进制后需要减去$2^7-1$,而double需要减去$2^{10}-1$。

float为例,最大的二进制表示为$0 11111110 11111111111111111111111_2$:

$$ 2^0 + 2^{-1} + 2^{-2} + \cdots + 2^{-23} = 2-2^{-23} $$

该数为$(1-2^{-24}) * 2^{128}$。

同理,最小正数为$0 00000001 00000000000000000000000_2$,即$2^{-126}$。

$0 00000000 00000000000000000000000_2$是$+0$,而$1 00000000 00000000000000000000000_2$是$-0$。

$0 11111111 00000000000000000000000_2$是$\infty$,而$1 11111111 00000000000000000000000_2$是$-\infty$。

4. 关于2的n次方的有趣事实

n次方十进制
12
24
38
416
532
664
7128
8256
9512
101024(千)
201048576(百万)
301073741824(十亿)

参考资料

  1. The Java Language Specification, Java SE 8 Edition

  2. Introduction to Programming in Java

  3. Wiki Two’s complement

  4. Java Primitive Data Types. Size, Range and Default Value of Basic Data Types

更新记录

2017年5月16日