初识JAVA虚拟机--数字编码【原码、反码、补码、IEEEE745】

一、 整数在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

浮 点 数 取 值 为 : s f l a g ∗ m ∗ 2 e − 127 浮点数取值为:sflag*m*2^{e-127} sflagm2e127

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;
1 ∗ 2 0 + 0 ∗ 2 − 1 + 1 ∗ 2 − 2 + 0 ∗ 2 − 3 + 0 ∗ 2 − 4 + 0 ∗ 2 − 5 + … … 1*2^0+0*2^{-1}+1*2^{-2}+0*2^{-3}+0*2^{-4}+0*2^{-5}+…… 120+021+122+023+024+025+
故 1 10000001 01000000000000000000000 的值为:
− 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 -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 12129127(120+021+122+023+024+025)=141.25=5
float的特殊数字

描述表示方式
正无穷0 11111111 00000000000000000000000
负无穷1 11111111 00000000000000000000000
NaN0 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自然实现这个转换。

学习笔记。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值