初识JAVA虚拟机--数字编码

纵然是瞬间 提交于 2020-02-26 17:40:31

一、 整数在Java虚拟机中的标识

java虚拟机中的整数:byte、short、int、long四种;分别标识8位、16位、32位、64位有符号整数。
整数在计算机中使用补码来表示,java虚拟机中也同理
原码:符号位加上数字的二进制表示

int 10 的原码为:00000000 00000000 00000000 00001010
int -10 的原码为: 10000000 00000000 00000000 00001010

反码:就是在原码的基础上符号位不变其余取反

int -10的反码为: 11111111 11111111 11111111 11110101

补码:负数的补码就是反码加1,正整数的补码就是原码本身

int 10 的补码:00000000 00000000 00000000 00001010
int -10的补码:11111111 11111111 11111111 11110110

int a = -10;
for (int i=0;i<32;i++){
	int t=(a & 0x80000000 >>>)>>>>(31-i);
	System.out.print(t);
}

以上代码可以打印-10在虚拟机内的时间表示:

11111111111111111111111111110110

使用补码作为计算机内的时间存储的好处

  • 可以统一数字0的表示
 由于0即非正数,也非负数
 如果0为正数:00000000 00000000 00000000 00000000
 如果0位负数:
 原码表示:10000000 00000000 00000000 00000000
 反码表示:11111111 11111111 11111111 11111111
 补码在反码的基础上加1,表示如下:
 补码表示:00000000 00000000 00000000 0000000
 可以看到使用补码作为整数编码,可以解决数字0的存储问题
  • 使用补码可以简化整数的加减法计算
使用补码可以简化整数的加减法计算,将减法计算视为加法计算,实现减法和加法的完全统一,实现正数和服务加法的统一
 如果 byte -6+5的过程如下:
 -6 的补码:11111010
 5  的补码:00000101
直接相加得: 11111111-1)
计算byte 4+6的运算过程如下:
4的补码:00000100
6的补码:00000110
计算可得:0000101010)
使用补码表示只需要将补码简单地相加,无需区别正数或者负数;

二、浮点数在java虚拟机中的表示

浮点数:float 32位和 double64位 两种
java虚拟机对于浮点存储参考了IEEE745的规范
以float为例:在IEEEE745规范中浮点数的组成分为三部分:符号位(1位)、字数位(8位)、尾数位(23位)

s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm

sflagm2e127 浮点数取值为:sflag*m*2^{e-127}
sflag表示符号,s为0时,sflag=1 ;s为1时,sflag=-1;m为尾数值,实际占用空间为23位,但是根据e的取值,有24位精度;当e全为0时,尾数位附近为0,否则尾数位附加为1;e为指数位,用8个字节;

float -51 10000001 01000000000000000000000

符号位为1标识负数,指数位为10000001,表示129.
尾数位为:01000000000000000000000 。因为e不为0,故实际的尾数位为101000000000000000000000
尾数位表示2的指数次幂的和每一位表示和数列中的对应项是否为0;
120+021+122+023+024+025+ 1*2^0+0*2^{-1}+1*2^{-2}+0*2^{-3}+0*2^{-4}+0*2^{-5}+……
故 1 10000001 01000000000000000000000 的值为:
12129127(120+021+122+023+024+025)=141.25=5 -1*2^{129-127}*(1*2^0+0*2^{-1}+1*2^{-2}+0*2^{-3}+0*2^{-4}+0*2^{-5})=-1*4*1.25=-5
float的特殊数字

描述 表示方式
正无穷 0 11111111 00000000000000000000000
负无穷 1 11111111 00000000000000000000000
NaN 0 11111111 10000000000000000000000
最大浮点数(3.4028235E38) 0 11111110 11111111111111111111111
最小规范化正浮点数(1.17549435E-38) 0 00000001 00000000000000000000000
最小正浮点数(1.4E-45) 0 00000000 00000000000000000000001
0 00000000 00000000000000000000000

注:指数为全为1标识无穷大和NaN的特殊数字;指数位全为0为非规范化的浮点数。

在Java中使用Float.floatToRawIntBits()函数可以获取一个单精度浮点数的IEEE 754 表示。

float a = -5;
System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(a)));

程序运行输出:

11000000101000000000000000000000

其中,Float.floatToRawIntBits()函数最终由native方法实现:如下

JNIEXPORT jint JNICALL
Java_java_lang_Float_floatToRawIntBits(JNIEnv *env, jclass unused, jfloat v)
{
	union {
		int i;
		float f;
	} u;
	u.f = (float)v;
	return (jint)u.i;
}

为了获取float的内部表示,使用了C语音中union自然实现这个转换。

学习笔记。。。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!